From 30fb37069c451223da1b1ccb1c2124571890abb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 15 Apr 2025 08:39:14 +0200 Subject: [PATCH 1/5] Add cargo-0.87.1 benchmark --- .../cargo-0.87.1/.cargo/config.toml | 10 + .../cargo-0.87.1/.cargo_vcs_info.json | 6 + .../.github/ISSUE_TEMPLATE/bug_report.yml | 43 + .../.github/ISSUE_TEMPLATE/config.yml | 10 + .../ISSUE_TEMPLATE/feature_request.yml | 35 + .../.github/ISSUE_TEMPLATE/tracking_issue.yml | 50 + .../.github/PULL_REQUEST_TEMPLATE.md | 36 + .../cargo-0.87.1/.github/renovate.json5 | 98 + .../cargo-0.87.1/.github/workflows/audit.yml | 30 + .../.github/workflows/contrib.yml | 52 + .../cargo-0.87.1/.github/workflows/main.yml | 278 + .../.github/workflows/release.yml | 33 + .../cargo-0.87.1/.gitignore | 14 + .../compile-benchmarks/cargo-0.87.1/.ignore | 15 + .../cargo-0.87.1/CHANGELOG.md | 3 + .../cargo-0.87.1/CODE_OF_CONDUCT.md | 3 + .../cargo-0.87.1/CONTRIBUTING.md | 19 + .../cargo-0.87.1/Cargo.toml | 395 + .../cargo-0.87.1/Cargo.toml.orig | 277 + .../cargo-0.87.1/LICENSE-APACHE | 201 + .../cargo-0.87.1/LICENSE-MIT | 23 + .../cargo-0.87.1/LICENSE-THIRD-PARTY | 1272 +++ .../compile-benchmarks/cargo-0.87.1/README.md | 129 + .../cargo-0.87.1/benches/README.md | 157 + .../cargo-0.87.1/benches/workspaces/cargo.tgz | Bin 0 -> 9967 bytes .../cargo-0.87.1/benches/workspaces/diem.tgz | Bin 0 -> 74635 bytes .../cargo-0.87.1/benches/workspaces/empty.tgz | Bin 0 -> 287 bytes .../benches/workspaces/gecko-dev.tgz | Bin 0 -> 49269 bytes .../benches/workspaces/rust-ws-inherit.tgz | Bin 0 -> 45123 bytes .../cargo-0.87.1/benches/workspaces/rust.tgz | Bin 0 -> 45064 bytes .../cargo-0.87.1/benches/workspaces/servo.tgz | Bin 0 -> 50573 bytes .../benches/workspaces/substrate.tgz | Bin 0 -> 92972 bytes .../cargo-0.87.1/benches/workspaces/tikv.tgz | Bin 0 -> 44476 bytes .../benches/workspaces/toml-rs.tgz | Bin 0 -> 1782 bytes .../compile-benchmarks/cargo-0.87.1/build.rs | 153 + .../cargo-0.87.1/ci/clean-test-output.sh | 8 + .../cargo-0.87.1/ci/dump-environment.sh | 22 + .../cargo-0.87.1/ci/fetch-smoke-test.sh | 27 + .../cargo-0.87.1/ci/generate.py | 49 + .../cargo-0.87.1/ci/validate-man.sh | 27 + .../cargo-0.87.1/ci/validate-version-bump.sh | 22 + .../cargo-0.87.1/clippy.toml | 11 + .../cargo-0.87.1/credential/README.md | 8 + .../compile-benchmarks/cargo-0.87.1/deny.toml | 243 + .../cargo-0.87.1/perf-config.json | 7 + .../cargo-0.87.1/publish.py | 72 + .../cargo-0.87.1/src/bin/cargo/cli.rs | 712 ++ .../src/bin/cargo/commands/add.rs | 409 + .../src/bin/cargo/commands/bench.rs | 80 + .../src/bin/cargo/commands/build.rs | 82 + .../src/bin/cargo/commands/check.rs | 59 + .../src/bin/cargo/commands/clean.rs | 198 + .../src/bin/cargo/commands/config.rs | 59 + .../src/bin/cargo/commands/doc.rs | 65 + .../src/bin/cargo/commands/fetch.rs | 27 + .../src/bin/cargo/commands/fix.rs | 107 + .../bin/cargo/commands/generate_lockfile.rs | 21 + .../src/bin/cargo/commands/git_checkout.rs | 16 + .../src/bin/cargo/commands/help.rs | 159 + .../src/bin/cargo/commands/info.rs | 35 + .../src/bin/cargo/commands/init.rs | 26 + .../src/bin/cargo/commands/install.rs | 316 + .../src/bin/cargo/commands/locate_project.rs | 95 + .../src/bin/cargo/commands/login.rs | 49 + .../src/bin/cargo/commands/logout.rs | 25 + .../src/bin/cargo/commands/metadata.rs | 60 + .../src/bin/cargo/commands/mod.rs | 133 + .../src/bin/cargo/commands/new.rs | 27 + .../src/bin/cargo/commands/owner.rs | 51 + .../src/bin/cargo/commands/package.rs | 92 + .../src/bin/cargo/commands/pkgid.rs | 31 + .../src/bin/cargo/commands/publish.rs | 84 + .../src/bin/cargo/commands/read_manifest.rs | 26 + .../src/bin/cargo/commands/remove.rs | 390 + .../src/bin/cargo/commands/report.rs | 51 + .../src/bin/cargo/commands/run.rs | 244 + .../src/bin/cargo/commands/rustc.rs | 112 + .../src/bin/cargo/commands/rustdoc.rs | 89 + .../src/bin/cargo/commands/search.rs | 38 + .../src/bin/cargo/commands/test.rs | 115 + .../src/bin/cargo/commands/tree.rs | 338 + .../src/bin/cargo/commands/uninstall.rs | 68 + .../src/bin/cargo/commands/update.rs | 113 + .../src/bin/cargo/commands/vendor.rs | 86 + .../src/bin/cargo/commands/verify_project.rs | 31 + .../src/bin/cargo/commands/version.rs | 18 + .../src/bin/cargo/commands/yank.rs | 64 + .../cargo-0.87.1/src/bin/cargo/main.rs | 441 + .../src/cargo/core/compiler/artifact.rs | 122 + .../src/cargo/core/compiler/build_config.rs | 274 + .../cargo/core/compiler/build_context/mod.rs | 144 + .../compiler/build_context/target_info.rs | 1197 +++ .../src/cargo/core/compiler/build_plan.rs | 160 + .../build_runner/compilation_files.rs | 841 ++ .../cargo/core/compiler/build_runner/mod.rs | 687 ++ .../src/cargo/core/compiler/compilation.rs | 502 ++ .../src/cargo/core/compiler/compile_kind.rs | 200 + .../src/cargo/core/compiler/crate_type.rs | 115 + .../src/cargo/core/compiler/custom_build.rs | 1336 +++ .../core/compiler/fingerprint/dep_info.rs | 762 ++ .../core/compiler/fingerprint/dirty_reason.rs | 330 + .../cargo/core/compiler/fingerprint/mod.rs | 2065 +++++ .../cargo/core/compiler/future_incompat.rs | 505 ++ .../src/cargo/core/compiler/job_queue/job.rs | 114 + .../core/compiler/job_queue/job_state.rs | 200 + .../src/cargo/core/compiler/job_queue/mod.rs | 1230 +++ .../src/cargo/core/compiler/layout.rs | 242 + .../src/cargo/core/compiler/links.rs | 60 + .../src/cargo/core/compiler/lto.rs | 194 + .../src/cargo/core/compiler/mod.rs | 1997 +++++ .../src/cargo/core/compiler/output_depinfo.rs | 184 + .../src/cargo/core/compiler/rustdoc.rs | 335 + .../src/cargo/core/compiler/standard_lib.rs | 250 + .../src/cargo/core/compiler/timings.js | 495 ++ .../src/cargo/core/compiler/timings.rs | 799 ++ .../src/cargo/core/compiler/unit.rs | 290 + .../cargo/core/compiler/unit_dependencies.rs | 1097 +++ .../src/cargo/core/compiler/unit_graph.rs | 129 + .../cargo-0.87.1/src/cargo/core/dependency.rs | 662 ++ .../cargo-0.87.1/src/cargo/core/features.rs | 1436 ++++ .../cargo-0.87.1/src/cargo/core/gc.rs | 505 ++ .../src/cargo/core/global_cache_tracker.rs | 1834 +++++ .../cargo-0.87.1/src/cargo/core/manifest.rs | 1189 +++ .../cargo-0.87.1/src/cargo/core/mod.rs | 34 + .../cargo-0.87.1/src/cargo/core/package.rs | 1209 +++ .../cargo-0.87.1/src/cargo/core/package_id.rs | 278 + .../src/cargo/core/package_id_spec.rs | 217 + .../cargo-0.87.1/src/cargo/core/profiles.rs | 1443 ++++ .../cargo-0.87.1/src/cargo/core/registry.rs | 1015 +++ .../src/cargo/core/resolver/conflict_cache.rs | 218 + .../src/cargo/core/resolver/context.rs | 204 + .../src/cargo/core/resolver/dep_cache.rs | 635 ++ .../src/cargo/core/resolver/encode.rs | 845 ++ .../src/cargo/core/resolver/errors.rs | 559 ++ .../src/cargo/core/resolver/features.rs | 978 +++ .../src/cargo/core/resolver/mod.rs | 1082 +++ .../src/cargo/core/resolver/resolve.rs | 492 ++ .../src/cargo/core/resolver/types.rs | 412 + .../src/cargo/core/resolver/version_prefs.rs | 312 + .../cargo-0.87.1/src/cargo/core/shell.rs | 701 ++ .../cargo-0.87.1/src/cargo/core/source_id.rs | 921 +++ .../cargo-0.87.1/src/cargo/core/summary.rs | 430 + .../cargo-0.87.1/src/cargo/core/workspace.rs | 2083 +++++ .../cargo-0.87.1/src/cargo/lib.rs | 233 + .../cargo-0.87.1/src/cargo/macros.rs | 49 + .../src/cargo/ops/cargo_add/crate_spec.rs | 62 + .../src/cargo/ops/cargo_add/mod.rs | 1229 +++ .../cargo-0.87.1/src/cargo/ops/cargo_clean.rs | 588 ++ .../cargo/ops/cargo_compile/compile_filter.rs | 309 + .../src/cargo/ops/cargo_compile/mod.rs | 965 +++ .../src/cargo/ops/cargo_compile/packages.rs | 274 + .../cargo/ops/cargo_compile/unit_generator.rs | 721 ++ .../src/cargo/ops/cargo_config.rs | 314 + .../cargo-0.87.1/src/cargo/ops/cargo_doc.rs | 166 + .../cargo-0.87.1/src/cargo/ops/cargo_fetch.rs | 82 + .../src/cargo/ops/cargo_install.rs | 951 +++ .../cargo-0.87.1/src/cargo/ops/cargo_new.rs | 1063 +++ .../src/cargo/ops/cargo_output_metadata.rs | 357 + .../src/cargo/ops/cargo_package/mod.rs | 1080 +++ .../src/cargo/ops/cargo_package/vcs.rs | 324 + .../src/cargo/ops/cargo_package/verify.rs | 193 + .../cargo-0.87.1/src/cargo/ops/cargo_pkgid.rs | 15 + .../src/cargo/ops/cargo_read_manifest.rs | 30 + .../src/cargo/ops/cargo_remove.rs | 65 + .../cargo-0.87.1/src/cargo/ops/cargo_run.rs | 110 + .../cargo-0.87.1/src/cargo/ops/cargo_test.rs | 465 ++ .../src/cargo/ops/cargo_uninstall.rs | 153 + .../src/cargo/ops/cargo_update.rs | 1234 +++ .../ops/common_for_install_and_uninstall.rs | 812 ++ .../cargo-0.87.1/src/cargo/ops/fix.rs | 1350 ++++ .../cargo-0.87.1/src/cargo/ops/lockfile.rs | 253 + .../cargo-0.87.1/src/cargo/ops/mod.rs | 100 + .../src/cargo/ops/registry/info/mod.rs | 222 + .../src/cargo/ops/registry/info/view.rs | 463 ++ .../src/cargo/ops/registry/login.rs | 64 + .../src/cargo/ops/registry/logout.rs | 20 + .../src/cargo/ops/registry/mod.rs | 371 + .../src/cargo/ops/registry/owner.rs | 93 + .../src/cargo/ops/registry/publish.rs | 796 ++ .../src/cargo/ops/registry/search.rs | 99 + .../src/cargo/ops/registry/yank.rs | 76 + .../cargo-0.87.1/src/cargo/ops/resolve.rs | 951 +++ .../src/cargo/ops/tree/format/mod.rs | 135 + .../src/cargo/ops/tree/format/parse.rs | 123 + .../cargo-0.87.1/src/cargo/ops/tree/graph.rs | 710 ++ .../cargo-0.87.1/src/cargo/ops/tree/mod.rs | 453 ++ .../cargo-0.87.1/src/cargo/ops/vendor.rs | 544 ++ .../cargo-0.87.1/src/cargo/sources/config.rs | 359 + .../src/cargo/sources/directory.rs | 277 + .../src/cargo/sources/git/known_hosts.rs | 927 +++ .../cargo-0.87.1/src/cargo/sources/git/mod.rs | 61 + .../src/cargo/sources/git/oxide.rs | 386 + .../src/cargo/sources/git/source.rs | 456 ++ .../src/cargo/sources/git/utils.rs | 1708 ++++ .../cargo-0.87.1/src/cargo/sources/mod.rs | 47 + .../cargo-0.87.1/src/cargo/sources/overlay.rs | 140 + .../cargo-0.87.1/src/cargo/sources/path.rs | 1209 +++ .../src/cargo/sources/registry/download.rs | 171 + .../src/cargo/sources/registry/http_remote.rs | 900 +++ .../src/cargo/sources/registry/index/cache.rs | 301 + .../src/cargo/sources/registry/index/mod.rs | 940 +++ .../src/cargo/sources/registry/local.rs | 207 + .../src/cargo/sources/registry/mod.rs | 1048 +++ .../src/cargo/sources/registry/remote.rs | 455 ++ .../src/cargo/sources/replaced.rs | 182 + .../cargo-0.87.1/src/cargo/sources/source.rs | 417 + .../cargo-0.87.1/src/cargo/util/auth/mod.rs | 716 ++ .../cargo-0.87.1/src/cargo/util/cache_lock.rs | 548 ++ .../src/cargo/util/canonical_url.rs | 75 + .../src/cargo/util/command_prelude.rs | 1366 ++++ .../cargo-0.87.1/src/cargo/util/context/de.rs | 656 ++ .../src/cargo/util/context/environment.rs | 193 + .../src/cargo/util/context/key.rs | 126 + .../src/cargo/util/context/mod.rs | 3077 +++++++ .../src/cargo/util/context/path.rs | 105 + .../src/cargo/util/context/target.rs | 244 + .../src/cargo/util/context/value.rs | 248 + .../cargo-0.87.1/src/cargo/util/counter.rs | 67 + .../cargo-0.87.1/src/cargo/util/cpu.rs | 244 + .../src/cargo/util/credential/adaptor.rs | 68 + .../src/cargo/util/credential/mod.rs | 8 + .../src/cargo/util/credential/paseto.rs | 233 + .../src/cargo/util/credential/process.rs | 115 + .../src/cargo/util/credential/token.rs | 95 + .../src/cargo/util/dependency_queue.rs | 254 + .../src/cargo/util/diagnostic_server.rs | 331 + .../src/cargo/util/edit_distance.rs | 147 + .../cargo-0.87.1/src/cargo/util/errors.rs | 346 + .../cargo-0.87.1/src/cargo/util/flock.rs | 606 ++ .../cargo-0.87.1/src/cargo/util/graph.rs | 303 + .../cargo-0.87.1/src/cargo/util/hasher.rs | 6 + .../cargo-0.87.1/src/cargo/util/hex.rs | 31 + .../cargo-0.87.1/src/cargo/util/hostname.rs | 77 + .../src/cargo/util/important_paths.rs | 45 + .../cargo-0.87.1/src/cargo/util/interning.rs | 181 + .../cargo-0.87.1/src/cargo/util/into_url.rs | 41 + .../src/cargo/util/into_url_with_base.rs | 50 + .../cargo-0.87.1/src/cargo/util/io.rs | 51 + .../cargo-0.87.1/src/cargo/util/job.rs | 149 + .../cargo-0.87.1/src/cargo/util/lints.rs | 725 ++ .../cargo-0.87.1/src/cargo/util/lockserver.rs | 173 + .../src/cargo/util/machine_message.rs | 115 + .../cargo-0.87.1/src/cargo/util/mod.rs | 193 + .../src/cargo/util/network/http.rs | 226 + .../src/cargo/util/network/mod.rs | 82 + .../src/cargo/util/network/proxy.rs | 42 + .../src/cargo/util/network/retry.rs | 317 + .../src/cargo/util/network/sleep.rs | 104 + .../cargo-0.87.1/src/cargo/util/progress.rs | 533 ++ .../cargo-0.87.1/src/cargo/util/queue.rs | 82 + .../src/cargo/util/restricted_names.rs | 50 + .../cargo-0.87.1/src/cargo/util/rustc.rs | 395 + .../src/cargo/util/semver_eval_ext.rs | 595 ++ .../cargo-0.87.1/src/cargo/util/semver_ext.rs | 282 + .../cargo-0.87.1/src/cargo/util/sqlite.rs | 118 + .../cargo-0.87.1/src/cargo/util/style.rs | 13 + .../src/cargo/util/toml/embedded.rs | 545 ++ .../cargo-0.87.1/src/cargo/util/toml/mod.rs | 3224 ++++++++ .../src/cargo/util/toml/targets.rs | 1201 +++ .../src/cargo/util/toml_mut/dependency.rs | 1322 +++ .../src/cargo/util/toml_mut/manifest.rs | 755 ++ .../src/cargo/util/toml_mut/mod.rs | 14 + .../src/cargo/util/toml_mut/upgrade.rs | 264 + .../cargo-0.87.1/src/cargo/util/vcs.rs | 104 + .../cargo-0.87.1/src/cargo/util/workspace.rs | 138 + .../cargo-0.87.1/src/cargo/version.rs | 80 + .../cargo-0.87.1/src/doc/.gitignore | 2 + .../cargo-0.87.1/src/doc/README.md | 71 + .../cargo-0.87.1/src/doc/book.toml | 20 + .../cargo-0.87.1/src/doc/contrib/README.md | 12 + .../cargo-0.87.1/src/doc/contrib/book.toml | 19 + .../src/doc/contrib/src/SUMMARY.md | 26 + .../src/doc/contrib/src/design.md | 101 + .../src/implementation/architecture.md | 5 + .../doc/contrib/src/implementation/console.md | 58 + .../contrib/src/implementation/debugging.md | 27 + .../contrib/src/implementation/filesystem.md | 21 + .../contrib/src/implementation/formatting.md | 17 + .../doc/contrib/src/implementation/index.md | 6 + .../contrib/src/implementation/packages.md | 52 + .../doc/contrib/src/implementation/schemas.md | 47 + .../contrib/src/implementation/subcommands.md | 25 + .../cargo-0.87.1/src/doc/contrib/src/index.md | 30 + .../src/doc/contrib/src/issues.md | 241 + .../src/doc/contrib/src/process/index.md | 119 + .../src/doc/contrib/src/process/release.md | 190 + .../src/doc/contrib/src/process/rfc.md | 64 + .../src/doc/contrib/src/process/security.md | 136 + .../src/doc/contrib/src/process/unstable.md | 135 + .../contrib/src/process/working-on-cargo.md | 188 + .../cargo-0.87.1/src/doc/contrib/src/team.md | 193 + .../src/doc/contrib/src/tests/crater.md | 122 + .../src/doc/contrib/src/tests/index.md | 20 + .../src/doc/contrib/src/tests/profiling.md | 49 + .../src/doc/contrib/src/tests/running.md | 78 + .../src/doc/contrib/src/tests/writing.md | 301 + .../cargo-0.87.1/src/doc/man/cargo-add.md | 202 + .../cargo-0.87.1/src/doc/man/cargo-bench.md | 188 + .../cargo-0.87.1/src/doc/man/cargo-build.md | 119 + .../cargo-0.87.1/src/doc/man/cargo-check.md | 102 + .../cargo-0.87.1/src/doc/man/cargo-clean.md | 96 + .../cargo-0.87.1/src/doc/man/cargo-doc.md | 132 + .../cargo-0.87.1/src/doc/man/cargo-fetch.md | 68 + .../cargo-0.87.1/src/doc/man/cargo-fix.md | 185 + .../src/doc/man/cargo-generate-lockfile.md | 53 + .../cargo-0.87.1/src/doc/man/cargo-help.md | 26 + .../cargo-0.87.1/src/doc/man/cargo-info.md | 67 + .../cargo-0.87.1/src/doc/man/cargo-init.md | 51 + .../cargo-0.87.1/src/doc/man/cargo-install.md | 236 + .../src/doc/man/cargo-locate-project.md | 66 + .../cargo-0.87.1/src/doc/man/cargo-login.md | 64 + .../cargo-0.87.1/src/doc/man/cargo-logout.md | 63 + .../src/doc/man/cargo-metadata.md | 407 + .../cargo-0.87.1/src/doc/man/cargo-new.md | 46 + .../cargo-0.87.1/src/doc/man/cargo-owner.md | 81 + .../cargo-0.87.1/src/doc/man/cargo-package.md | 165 + .../cargo-0.87.1/src/doc/man/cargo-pkgid.md | 100 + .../cargo-0.87.1/src/doc/man/cargo-publish.md | 180 + .../cargo-0.87.1/src/doc/man/cargo-remove.md | 97 + .../cargo-0.87.1/src/doc/man/cargo-report.md | 42 + .../cargo-0.87.1/src/doc/man/cargo-run.md | 118 + .../cargo-0.87.1/src/doc/man/cargo-rustc.md | 149 + .../cargo-0.87.1/src/doc/man/cargo-rustdoc.md | 121 + .../cargo-0.87.1/src/doc/man/cargo-search.md | 53 + .../cargo-0.87.1/src/doc/man/cargo-test.md | 223 + .../cargo-0.87.1/src/doc/man/cargo-tree.md | 273 + .../src/doc/man/cargo-uninstall.md | 63 + .../cargo-0.87.1/src/doc/man/cargo-update.md | 125 + .../cargo-0.87.1/src/doc/man/cargo-vendor.md | 107 + .../cargo-0.87.1/src/doc/man/cargo-version.md | 41 + .../cargo-0.87.1/src/doc/man/cargo-yank.md | 121 + .../cargo-0.87.1/src/doc/man/cargo.md | 245 + .../src/doc/man/generated_txt/cargo-add.txt | 292 + .../src/doc/man/generated_txt/cargo-bench.txt | 466 ++ .../src/doc/man/generated_txt/cargo-build.txt | 404 + .../src/doc/man/generated_txt/cargo-check.txt | 389 + .../src/doc/man/generated_txt/cargo-clean.txt | 198 + .../src/doc/man/generated_txt/cargo-doc.txt | 351 + .../src/doc/man/generated_txt/cargo-fetch.txt | 173 + .../src/doc/man/generated_txt/cargo-fix.txt | 461 ++ .../generated_txt/cargo-generate-lockfile.txt | 152 + .../src/doc/man/generated_txt/cargo-help.txt | 23 + .../src/doc/man/generated_txt/cargo-info.txt | 155 + .../src/doc/man/generated_txt/cargo-init.txt | 136 + .../doc/man/generated_txt/cargo-install.txt | 415 + .../generated_txt/cargo-locate-project.txt | 119 + .../src/doc/man/generated_txt/cargo-login.txt | 126 + .../doc/man/generated_txt/cargo-logout.txt | 122 + .../doc/man/generated_txt/cargo-metadata.txt | 517 ++ .../src/doc/man/generated_txt/cargo-new.txt | 131 + .../src/doc/man/generated_txt/cargo-owner.txt | 146 + .../doc/man/generated_txt/cargo-package.txt | 339 + .../src/doc/man/generated_txt/cargo-pkgid.txt | 203 + .../doc/man/generated_txt/cargo-publish.txt | 332 + .../doc/man/generated_txt/cargo-remove.txt | 176 + .../doc/man/generated_txt/cargo-report.txt | 34 + .../src/doc/man/generated_txt/cargo-run.txt | 303 + .../src/doc/man/generated_txt/cargo-rustc.txt | 411 + .../doc/man/generated_txt/cargo-rustdoc.txt | 378 + .../doc/man/generated_txt/cargo-search.txt | 109 + .../src/doc/man/generated_txt/cargo-test.txt | 505 ++ .../src/doc/man/generated_txt/cargo-tree.txt | 419 + .../doc/man/generated_txt/cargo-uninstall.txt | 120 + .../doc/man/generated_txt/cargo-update.txt | 219 + .../doc/man/generated_txt/cargo-vendor.txt | 194 + .../doc/man/generated_txt/cargo-version.txt | 32 + .../src/doc/man/generated_txt/cargo-yank.txt | 191 + .../src/doc/man/generated_txt/cargo.txt | 311 + .../man/includes/description-install-root.md | 7 + .../man/includes/description-one-target.md | 4 + .../src/doc/man/includes/options-display.md | 24 + .../man/includes/options-future-incompat.md | 6 + .../includes/options-ignore-rust-version.md | 3 + .../src/doc/man/includes/options-index.md | 3 + .../src/doc/man/includes/options-jobs.md | 8 + .../doc/man/includes/options-keep-going.md | 10 + .../src/doc/man/includes/options-locked.md | 32 + .../doc/man/includes/options-lockfile-path.md | 12 + .../doc/man/includes/options-manifest-path.md | 4 + .../man/includes/options-message-format.md | 21 + .../src/doc/man/includes/options-new.md | 39 + .../doc/man/includes/options-output-format.md | 9 + .../includes/options-profile-legacy-check.md | 10 + .../src/doc/man/includes/options-profile.md | 4 + .../src/doc/man/includes/options-registry.md | 6 + .../src/doc/man/includes/options-release.md | 4 + .../doc/man/includes/options-target-dir.md | 13 + .../doc/man/includes/options-target-triple.md | 16 + .../options-targets-bin-auto-built.md | 8 + .../man/includes/options-targets-lib-bin.md | 12 + .../src/doc/man/includes/options-targets.md | 57 + .../src/doc/man/includes/options-test.md | 14 + .../src/doc/man/includes/options-timings.md | 16 + .../src/doc/man/includes/options-token.md | 11 + .../doc/man/includes/section-environment.md | 4 + .../doc/man/includes/section-exit-status.md | 4 + .../src/doc/man/includes/section-features.md | 26 + .../man/includes/section-options-common.md | 39 + .../man/includes/section-options-package.md | 13 + .../man/includes/section-package-selection.md | 42 + .../cargo-0.87.1/src/doc/src/CHANGELOG.md | 6155 ++++++++++++++ .../cargo-0.87.1/src/doc/src/SUMMARY.md | 102 + .../doc/src/appendix/git-authentication.md | 96 + .../src/doc/src/appendix/glossary.md | 274 + .../src/doc/src/commands/build-commands.md | 16 + .../src/doc/src/commands/cargo-add.md | 310 + .../src/doc/src/commands/cargo-bench.md | 508 ++ .../src/doc/src/commands/cargo-build.md | 441 + .../src/doc/src/commands/cargo-check.md | 423 + .../src/doc/src/commands/cargo-clean.md | 216 + .../src/doc/src/commands/cargo-clippy.md | 20 + .../src/doc/src/commands/cargo-doc.md | 390 + .../src/doc/src/commands/cargo-fetch.md | 179 + .../src/doc/src/commands/cargo-fix.md | 502 ++ .../src/doc/src/commands/cargo-fmt.md | 20 + .../src/commands/cargo-generate-lockfile.md | 164 + .../src/doc/src/commands/cargo-help.md | 26 + .../src/doc/src/commands/cargo-info.md | 168 + .../src/doc/src/commands/cargo-init.md | 157 + .../src/doc/src/commands/cargo-install.md | 446 + .../doc/src/commands/cargo-locate-project.md | 139 + .../src/doc/src/commands/cargo-login.md | 138 + .../src/doc/src/commands/cargo-logout.md | 137 + .../src/doc/src/commands/cargo-metadata.md | 541 ++ .../src/doc/src/commands/cargo-miri.md | 22 + .../src/doc/src/commands/cargo-new.md | 152 + .../src/doc/src/commands/cargo-owner.md | 169 + .../src/doc/src/commands/cargo-package.md | 365 + .../src/doc/src/commands/cargo-pkgid.md | 210 + .../src/doc/src/commands/cargo-publish.md | 351 + .../src/doc/src/commands/cargo-remove.md | 202 + .../src/doc/src/commands/cargo-report.md | 43 + .../src/doc/src/commands/cargo-run.md | 339 + .../src/doc/src/commands/cargo-rustc.md | 443 + .../src/doc/src/commands/cargo-rustdoc.md | 418 + .../src/doc/src/commands/cargo-search.md | 129 + .../src/doc/src/commands/cargo-test.md | 551 ++ .../src/doc/src/commands/cargo-tree.md | 442 + .../src/doc/src/commands/cargo-uninstall.md | 139 + .../src/doc/src/commands/cargo-update.md | 232 + .../src/doc/src/commands/cargo-vendor.md | 217 + .../src/doc/src/commands/cargo-version.md | 42 + .../src/doc/src/commands/cargo-yank.md | 207 + .../src/doc/src/commands/cargo.md | 342 + .../src/commands/deprecated-and-removed.md | 10 + .../src/doc/src/commands/general-commands.md | 4 + .../src/doc/src/commands/index.md | 7 + .../src/doc/src/commands/manifest-commands.md | 12 + .../src/doc/src/commands/package-commands.md | 6 + .../doc/src/commands/publishing-commands.md | 7 + .../cargo-0.87.1/src/doc/src/faq.md | 296 + .../doc/src/getting-started/first-steps.md | 82 + .../src/doc/src/getting-started/index.md | 9 + .../doc/src/getting-started/installation.md | 38 + .../src/doc/src/guide/cargo-home.md | 93 + .../doc/src/guide/cargo-toml-vs-cargo-lock.md | 104 + .../doc/src/guide/continuous-integration.md | 210 + .../doc/src/guide/creating-a-new-project.md | 97 + .../src/doc/src/guide/dependencies.md | 93 + .../cargo-0.87.1/src/doc/src/guide/index.md | 15 + .../src/doc/src/guide/project-layout.md | 61 + .../cargo-0.87.1/src/doc/src/guide/tests.md | 44 + .../src/doc/src/guide/why-cargo-exists.md | 65 + .../guide/working-on-an-existing-project.md | 24 + .../src/doc/src/images/Cargo-Logo-Small.png | Bin 0 -> 58168 bytes .../src/doc/src/images/auth-level-acl.png | Bin 0 -> 90300 bytes .../src/doc/src/images/build-info.png | Bin 0 -> 28150 bytes .../src/doc/src/images/build-unit-time.png | Bin 0 -> 27728 bytes .../images/cargo-concurrency-over-time.png | Bin 0 -> 31220 bytes .../src/doc/src/images/org-level-acl.png | Bin 0 -> 76572 bytes .../src/doc/src/images/winapi-features.svg | 3 + .../cargo-0.87.1/src/doc/src/index.md | 48 + .../src/doc/src/reference/build-cache.md | 108 + .../src/reference/build-script-examples.md | 509 ++ .../src/doc/src/reference/build-scripts.md | 536 ++ .../src/doc/src/reference/cargo-targets.md | 393 + .../src/doc/src/reference/config.md | 1390 ++++ .../reference/credential-provider-protocol.md | 237 + .../src/reference/environment-variables.md | 430 + .../src/doc/src/reference/external-tools.md | 309 + .../doc/src/reference/features-examples.md | 187 + .../src/doc/src/reference/features.md | 530 ++ .../src/reference/future-incompat-report.md | 37 + .../src/doc/src/reference/index.md | 33 + .../src/doc/src/reference/lints.md | 28 + .../src/doc/src/reference/manifest.md | 671 ++ .../src/reference/overriding-dependencies.md | 359 + .../src/doc/src/reference/pkgid-spec.md | 75 + .../src/doc/src/reference/profiles.md | 488 ++ .../src/doc/src/reference/publishing.md | 296 + .../src/doc/src/reference/registries.md | 157 + .../src/reference/registry-authentication.md | 99 + .../src/doc/src/reference/registry-index.md | 327 + .../src/doc/src/reference/registry-web-api.md | 362 + .../src/doc/src/reference/resolver.md | 715 ++ .../doc/src/reference/running-a-registry.md | 20 + .../src/doc/src/reference/rust-version.md | 164 + .../src/doc/src/reference/semver.md | 2319 ++++++ .../doc/src/reference/source-replacement.md | 130 + .../src/reference/specifying-dependencies.md | 675 ++ .../src/doc/src/reference/timings.md | 66 + .../src/doc/src/reference/unstable.md | 1995 +++++ .../src/doc/src/reference/workspaces.md | 315 + .../cargo-0.87.1/src/doc/theme/favicon.png | Bin 0 -> 15086 bytes .../cargo-0.87.1/src/doc/theme/head.hbs | 5 + .../cargo-0.87.1/src/etc/_cargo | 479 ++ .../cargo-0.87.1/src/etc/cargo.bashcomp.sh | 283 + .../cargo-0.87.1/src/etc/man/cargo-add.1 | 383 + .../cargo-0.87.1/src/etc/man/cargo-bench.1 | 573 ++ .../cargo-0.87.1/src/etc/man/cargo-build.1 | 496 ++ .../cargo-0.87.1/src/etc/man/cargo-check.1 | 477 ++ .../cargo-0.87.1/src/etc/man/cargo-clean.1 | 245 + .../cargo-0.87.1/src/etc/man/cargo-doc.1 | 427 + .../cargo-0.87.1/src/etc/man/cargo-fetch.1 | 201 + .../cargo-0.87.1/src/etc/man/cargo-fix.1 | 574 ++ .../src/etc/man/cargo-generate-lockfile.1 | 187 + .../cargo-0.87.1/src/etc/man/cargo-help.1 | 34 + .../cargo-0.87.1/src/etc/man/cargo-info.1 | 201 + .../cargo-0.87.1/src/etc/man/cargo-init.1 | 171 + .../cargo-0.87.1/src/etc/man/cargo-install.1 | 536 ++ .../src/etc/man/cargo-locate-project.1 | 150 + .../cargo-0.87.1/src/etc/man/cargo-login.1 | 154 + .../cargo-0.87.1/src/etc/man/cargo-logout.1 | 153 + .../cargo-0.87.1/src/etc/man/cargo-metadata.1 | 563 ++ .../cargo-0.87.1/src/etc/man/cargo-new.1 | 166 + .../cargo-0.87.1/src/etc/man/cargo-owner.1 | 197 + .../cargo-0.87.1/src/etc/man/cargo-package.1 | 414 + .../cargo-0.87.1/src/etc/man/cargo-pkgid.1 | 272 + .../cargo-0.87.1/src/etc/man/cargo-publish.1 | 382 + .../cargo-0.87.1/src/etc/man/cargo-remove.1 | 228 + .../cargo-0.87.1/src/etc/man/cargo-report.1 | 48 + .../cargo-0.87.1/src/etc/man/cargo-run.1 | 373 + .../cargo-0.87.1/src/etc/man/cargo-rustc.1 | 506 ++ .../cargo-0.87.1/src/etc/man/cargo-rustdoc.1 | 461 ++ .../cargo-0.87.1/src/etc/man/cargo-search.1 | 138 + .../cargo-0.87.1/src/etc/man/cargo-test.1 | 624 ++ .../cargo-0.87.1/src/etc/man/cargo-tree.1 | 534 ++ .../src/etc/man/cargo-uninstall.1 | 161 + .../cargo-0.87.1/src/etc/man/cargo-update.1 | 283 + .../cargo-0.87.1/src/etc/man/cargo-vendor.1 | 251 + .../cargo-0.87.1/src/etc/man/cargo-version.1 | 52 + .../cargo-0.87.1/src/etc/man/cargo-yank.1 | 248 + .../cargo-0.87.1/src/etc/man/cargo.1 | 414 + .../cargo-0.87.1/tests/build-std/main.rs | 443 + .../tests/testsuite/advanced_env.rs | 37 + .../tests/testsuite/alt_registry.rs | 1982 +++++ .../tests/testsuite/artifact_dep.rs | 3409 ++++++++ .../tests/testsuite/artifact_dir.rs | 418 + .../tests/testsuite/bad_config.rs | 3045 +++++++ .../tests/testsuite/bad_manifest_path.rs | 412 + .../cargo-0.87.1/tests/testsuite/bench.rs | 2129 +++++ .../tests/testsuite/binary_name.rs | 527 ++ .../cargo-0.87.1/tests/testsuite/build.rs | 6749 ++++++++++++++++ .../tests/testsuite/build_plan.rs | 244 + .../tests/testsuite/build_script.rs | 6089 ++++++++++++++ .../tests/testsuite/build_script_env.rs | 454 ++ .../testsuite/build_script_extra_link_arg.rs | 405 + .../tests/testsuite/cache_lock.rs | 307 + .../tests/testsuite/cache_messages.rs | 519 ++ .../tests/testsuite/cargo/help/mod.rs | 13 + .../testsuite/cargo/help/stdout.term.svg | 108 + .../cargo-0.87.1/tests/testsuite/cargo/mod.rs | 2 + .../tests/testsuite/cargo/z_help/mod.rs | 14 + .../testsuite/cargo/z_help/stdout.term.svg | 107 + .../testsuite/cargo_add/add_basic/mod.rs | 37 + .../cargo_add/add_basic/stderr.term.svg | 31 + .../testsuite/cargo_add/add_multiple/mod.rs | 39 + .../cargo_add/add_multiple/stderr.term.svg | 33 + .../mod.rs | 36 + .../stderr.term.svg | 51 + .../mod.rs | 24 + .../stderr.term.svg | 27 + .../testsuite/cargo_add/add_toolchain/mod.rs | 24 + .../cargo_add/add_toolchain/stderr.term.svg | 29 + .../tests/testsuite/cargo_add/build/mod.rs | 39 + .../testsuite/cargo_add/build/stderr.term.svg | 33 + .../build_prefer_existing_version/mod.rs | 39 + .../stderr.term.svg | 36 + .../cargo_add/change_rename_target/mod.rs | 39 + .../change_rename_target/stderr.term.svg | 33 + .../cargo_add/cyclic_features/mod.rs | 31 + .../cargo_add/cyclic_features/stderr.term.svg | 37 + .../cargo_add/default_features/mod.rs | 39 + .../default_features/stderr.term.svg | 37 + .../deprecated_default_features/mod.rs | 37 + .../stderr.term.svg | 27 + .../cargo_add/deprecated_section/mod.rs | 37 + .../deprecated_section/stderr.term.svg | 27 + .../cargo_add/detect_workspace_inherit/mod.rs | 26 + .../detect_workspace_inherit/stderr.term.svg | 27 + .../detect_workspace_inherit_features/mod.rs | 26 + .../stderr.term.svg | 46 + .../detect_workspace_inherit_optional/mod.rs | 26 + .../stderr.term.svg | 29 + .../detect_workspace_inherit_path_base/mod.rs | 27 + .../stderr.term.svg | 27 + .../detect_workspace_inherit_public/mod.rs | 27 + .../stderr.term.svg | 27 + .../tests/testsuite/cargo_add/dev/mod.rs | 39 + .../testsuite/cargo_add/dev/stderr.term.svg | 33 + .../cargo_add/dev_build_conflict/mod.rs | 37 + .../dev_build_conflict/stderr.term.svg | 42 + .../in/.cargo/config.toml | 2 + .../cargo_add/dev_existing_path_base/mod.rs | 25 + .../dev_existing_path_base/stderr.term.svg | 29 + .../dev_prefer_existing_version/mod.rs | 39 + .../stderr.term.svg | 36 + .../tests/testsuite/cargo_add/dry_run/mod.rs | 37 + .../cargo_add/dry_run/stderr.term.svg | 32 + .../testsuite/cargo_add/empty_dep_name/mod.rs | 25 + .../cargo_add/empty_dep_name/stderr.term.svg | 27 + .../tests/testsuite/cargo_add/features/mod.rs | 32 + .../cargo_add/features/stderr.term.svg | 42 + .../features_activated_over_limit/mod.rs | 39 + .../stderr.term.svg | 37 + .../features_deactivated_over_limit/mod.rs | 39 + .../stderr.term.svg | 95 + .../testsuite/cargo_add/features_empty/mod.rs | 32 + .../cargo_add/features_empty/stderr.term.svg | 42 + .../features_multiple_occurrences/mod.rs | 32 + .../stderr.term.svg | 42 + .../cargo_add/features_preserve/mod.rs | 32 + .../features_preserve/stderr.term.svg | 42 + .../cargo_add/features_spaced_values/mod.rs | 32 + .../features_spaced_values/stderr.term.svg | 42 + .../cargo_add/features_unknown/mod.rs | 32 + .../features_unknown/stderr.term.svg | 36 + .../features_unknown_no_features/mod.rs | 37 + .../stderr.term.svg | 34 + .../tests/testsuite/cargo_add/git/mod.rs | 35 + .../testsuite/cargo_add/git/stderr.term.svg | 33 + .../testsuite/cargo_add/git_branch/mod.rs | 38 + .../cargo_add/git_branch/stderr.term.svg | 33 + .../cargo_add/git_conflicts_namever/mod.rs | 41 + .../git_conflicts_namever/stderr.term.svg | 27 + .../tests/testsuite/cargo_add/git_dev/mod.rs | 35 + .../cargo_add/git_dev/stderr.term.svg | 33 + .../cargo_add/git_inferred_name/mod.rs | 35 + .../git_inferred_name/stderr.term.svg | 35 + .../git_inferred_name_multiple/mod.rs | 75 + .../stderr.term.svg | 36 + .../cargo_add/git_multiple_names/mod.rs | 53 + .../git_multiple_names/stderr.term.svg | 35 + .../git_multiple_packages_features/mod.rs | 64 + .../stderr.term.svg | 37 + .../testsuite/cargo_add/git_registry/mod.rs | 54 + .../cargo_add/git_registry/stderr.term.svg | 38 + .../tests/testsuite/cargo_add/git_rev/mod.rs | 37 + .../cargo_add/git_rev/stderr.term.svg | 33 + .../tests/testsuite/cargo_add/git_tag/mod.rs | 37 + .../cargo_add/git_tag/stderr.term.svg | 33 + .../tests/testsuite/cargo_add/help/mod.rs | 14 + .../testsuite/cargo_add/help/stdout.term.svg | 308 + .../cargo_add/infer_prerelease/mod.rs | 27 + .../infer_prerelease/stderr.term.svg | 31 + .../testsuite/cargo_add/invalid_arg/mod.rs | 37 + .../cargo_add/invalid_arg/stderr.term.svg | 46 + .../cargo_add/invalid_git_name/mod.rs | 35 + .../invalid_git_name/stderr.term.svg | 30 + .../invalid_key_inherit_dependency/mod.rs | 24 + .../stderr.term.svg | 27 + .../mod.rs | 24 + .../stderr.term.svg | 27 + .../mod.rs | 24 + .../stderr.term.svg | 27 + .../cargo_add/invalid_manifest/mod.rs | 37 + .../invalid_manifest/stderr.term.svg | 40 + .../cargo_add/invalid_name_external/mod.rs | 26 + .../invalid_name_external/stderr.term.svg | 30 + .../testsuite/cargo_add/invalid_path/mod.rs | 26 + .../cargo_add/invalid_path/stderr.term.svg | 45 + .../cargo_add/invalid_path_name/mod.rs | 38 + .../invalid_path_name/stderr.term.svg | 27 + .../cargo_add/invalid_path_self/mod.rs | 26 + .../invalid_path_self/stderr.term.svg | 30 + .../cargo_add/invalid_target_empty/mod.rs | 37 + .../invalid_target_empty/stderr.term.svg | 33 + .../testsuite/cargo_add/invalid_vers/mod.rs | 37 + .../cargo_add/invalid_vers/stderr.term.svg | 33 + .../testsuite/cargo_add/list_features/mod.rs | 32 + .../cargo_add/list_features/stderr.term.svg | 42 + .../cargo_add/list_features_path/mod.rs | 43 + .../list_features_path/stderr.term.svg | 46 + .../list_features_path_no_default/mod.rs | 48 + .../stderr.term.svg | 46 + .../testsuite/cargo_add/locked_changed/mod.rs | 37 + .../cargo_add/locked_changed/stderr.term.svg | 32 + .../cargo_add/locked_unchanged/mod.rs | 37 + .../locked_unchanged/stderr.term.svg | 29 + .../cargo_add/lockfile_updated/mod.rs | 39 + .../lockfile_updated/stderr.term.svg | 34 + .../cargo_add/manifest_path_package/mod.rs | 44 + .../manifest_path_package/stderr.term.svg | 27 + .../cargo_add/merge_activated_features/mod.rs | 24 + .../merge_activated_features/stderr.term.svg | 46 + .../tests/testsuite/cargo_add/mod.rs | 153 + .../multiple_conflicts_with_features/mod.rs | 43 + .../stderr.term.svg | 27 + .../multiple_conflicts_with_rename/mod.rs | 39 + .../stderr.term.svg | 27 + .../tests/testsuite/cargo_add/namever/mod.rs | 39 + .../cargo_add/namever/stderr.term.svg | 39 + .../tests/testsuite/cargo_add/no_args/mod.rs | 25 + .../cargo_add/no_args/stderr.term.svg | 43 + .../cargo_add/no_default_features/mod.rs | 39 + .../no_default_features/stderr.term.svg | 37 + .../testsuite/cargo_add/no_optional/mod.rs | 27 + .../cargo_add/no_optional/stderr.term.svg | 31 + .../testsuite/cargo_add/no_public/mod.rs | 27 + .../cargo_add/no_public/stderr.term.svg | 31 + .../cargo_add/normalize_name_git/mod.rs | 35 + .../normalize_name_git/stderr.term.svg | 30 + .../cargo_add/normalize_name_path/mod.rs | 38 + .../normalize_name_path/stderr.term.svg | 27 + .../normalize_name_path_existing/mod.rs | 24 + .../stderr.term.svg | 30 + .../cargo_add/normalize_name_registry/mod.rs | 42 + .../normalize_name_registry/stderr.term.svg | 65 + .../normalize_name_registry_existing/mod.rs | 32 + .../stderr.term.svg | 45 + .../normalize_name_registry_yanked/mod.rs | 31 + .../stderr.term.svg | 34 + .../normalize_name_workspace_dep/mod.rs | 29 + .../stderr.term.svg | 34 + .../cargo_add/offline_empty_cache/mod.rs | 37 + .../offline_empty_cache/stderr.term.svg | 27 + .../tests/testsuite/cargo_add/optional/mod.rs | 27 + .../cargo_add/optional/stderr.term.svg | 33 + .../overwrite_default_features/mod.rs | 39 + .../stderr.term.svg | 37 + .../mod.rs | 39 + .../stderr.term.svg | 37 + .../cargo_add/overwrite_features/mod.rs | 32 + .../overwrite_features/stderr.term.svg | 42 + .../cargo_add/overwrite_git_with_path/mod.rs | 38 + .../overwrite_git_with_path/stderr.term.svg | 31 + .../overwrite_inherit_features_noop/mod.rs | 26 + .../stderr.term.svg | 31 + .../cargo_add/overwrite_inherit_noop/mod.rs | 26 + .../overwrite_inherit_noop/stderr.term.svg | 27 + .../overwrite_inherit_optional_noop/mod.rs | 26 + .../stderr.term.svg | 29 + .../overwrite_inline_features/mod.rs | 45 + .../overwrite_inline_features/stderr.term.svg | 43 + .../cargo_add/overwrite_name_dev_noop/mod.rs | 33 + .../overwrite_name_dev_noop/stderr.term.svg | 35 + .../cargo_add/overwrite_name_noop/mod.rs | 33 + .../overwrite_name_noop/stderr.term.svg | 37 + .../overwrite_no_default_features/mod.rs | 39 + .../stderr.term.svg | 37 + .../mod.rs | 39 + .../stderr.term.svg | 37 + .../cargo_add/overwrite_no_optional/mod.rs | 27 + .../overwrite_no_optional/stderr.term.svg | 31 + .../mod.rs | 27 + .../stderr.term.svg | 33 + .../cargo_add/overwrite_no_public/mod.rs | 27 + .../overwrite_no_public/stderr.term.svg | 31 + .../overwrite_no_public_with_public/mod.rs | 27 + .../stderr.term.svg | 31 + .../cargo_add/overwrite_optional/mod.rs | 27 + .../overwrite_optional/stderr.term.svg | 33 + .../mod.rs | 33 + .../stderr.term.svg | 42 + .../overwrite_optional_with_optional/mod.rs | 27 + .../stderr.term.svg | 31 + .../in/.cargo/config.toml | 2 + .../overwrite_path_base_with_version/mod.rs | 29 + .../stderr.term.svg | 35 + .../cargo_add/overwrite_path_noop/mod.rs | 33 + .../overwrite_path_noop/stderr.term.svg | 37 + .../overwrite_path_with_version/mod.rs | 38 + .../stderr.term.svg | 37 + .../overwrite_preserves_inline_table/mod.rs | 32 + .../stderr.term.svg | 42 + .../cargo_add/overwrite_public/mod.rs | 27 + .../overwrite_public/stderr.term.svg | 31 + .../overwrite_public_with_no_public/mod.rs | 27 + .../stderr.term.svg | 31 + .../overwrite_rename_with_no_rename/mod.rs | 37 + .../stderr.term.svg | 35 + .../overwrite_rename_with_rename/mod.rs | 37 + .../stderr.term.svg | 35 + .../overwrite_rename_with_rename_noop/mod.rs | 37 + .../stderr.term.svg | 37 + .../overwrite_version_with_git/mod.rs | 46 + .../stderr.term.svg | 35 + .../overwrite_version_with_path/mod.rs | 38 + .../stderr.term.svg | 31 + .../cargo_add/overwrite_with_rename/mod.rs | 37 + .../overwrite_with_rename/stderr.term.svg | 35 + .../cargo_add/overwrite_workspace_dep/mod.rs | 26 + .../overwrite_workspace_dep/stderr.term.svg | 27 + .../overwrite_workspace_dep_features/mod.rs | 26 + .../stderr.term.svg | 46 + .../tests/testsuite/cargo_add/path/mod.rs | 38 + .../testsuite/cargo_add/path/stderr.term.svg | 29 + .../cargo_add/path_base/in/.cargo/config.toml | 2 + .../testsuite/cargo_add/path_base/mod.rs | 25 + .../cargo_add/path_base/stderr.term.svg | 29 + .../in/.cargo/config.toml | 2 + .../cargo_add/path_base_inferred_name/mod.rs | 25 + .../path_base_inferred_name/stderr.term.svg | 29 + .../path_base_missing_base_path/mod.rs | 25 + .../stderr.term.svg | 27 + .../cargo_add/path_base_unstable/mod.rs | 24 + .../path_base_unstable/stderr.term.svg | 37 + .../tests/testsuite/cargo_add/path_dev/mod.rs | 38 + .../cargo_add/path_dev/stderr.term.svg | 29 + .../cargo_add/path_inferred_name/mod.rs | 38 + .../path_inferred_name/stderr.term.svg | 29 + .../mod.rs | 26 + .../stderr.term.svg | 27 + .../cargo_add/preserve_dep_std_table/mod.rs | 32 + .../preserve_dep_std_table/stderr.term.svg | 42 + .../cargo_add/preserve_features_sorted/mod.rs | 33 + .../preserve_features_sorted/stderr.term.svg | 43 + .../cargo_add/preserve_features_table/mod.rs | 32 + .../preserve_features_table/stderr.term.svg | 42 + .../preserve_features_unsorted/mod.rs | 33 + .../stderr.term.svg | 43 + .../cargo_add/preserve_sorted/mod.rs | 39 + .../cargo_add/preserve_sorted/stderr.term.svg | 37 + .../cargo_add/preserve_unsorted/mod.rs | 39 + .../preserve_unsorted/stderr.term.svg | 37 + .../tests/testsuite/cargo_add/public/mod.rs | 27 + .../cargo_add/public/stderr.term.svg | 31 + .../tests/testsuite/cargo_add/quiet/mod.rs | 31 + .../tests/testsuite/cargo_add/registry/mod.rs | 41 + .../cargo_add/registry/stderr.term.svg | 33 + .../tests/testsuite/cargo_add/rename/mod.rs | 37 + .../cargo_add/rename/stderr.term.svg | 31 + .../testsuite/cargo_add/require_weak/mod.rs | 32 + .../cargo_add/require_weak/stderr.term.svg | 42 + .../cargo_add/rust_version_ignore/mod.rs | 34 + .../rust_version_ignore/stderr.term.svg | 31 + .../rust_version_incompatible/mod.rs | 36 + .../rust_version_incompatible/stderr.term.svg | 32 + .../cargo_add/rust_version_latest/mod.rs | 33 + .../rust_version_latest/stderr.term.svg | 31 + .../cargo_add/rust_version_older/mod.rs | 33 + .../rust_version_older/stderr.term.svg | 37 + .../testsuite/cargo_add/rustc_ignore/mod.rs | 37 + .../cargo_add/rustc_ignore/stderr.term.svg | 35 + .../cargo_add/rustc_incompatible/mod.rs | 30 + .../rustc_incompatible/stderr.term.svg | 32 + .../testsuite/cargo_add/rustc_latest/mod.rs | 36 + .../cargo_add/rustc_latest/stderr.term.svg | 37 + .../testsuite/cargo_add/rustc_older/mod.rs | 36 + .../cargo_add/rustc_older/stderr.term.svg | 37 + .../script_bare/in/cargo-test-fixture.rs | 1 + .../testsuite/cargo_add/script_bare/mod.rs | 39 + .../script_bare/out/cargo-test-fixture.rs | 6 + .../cargo_add/script_bare/stderr.term.svg | 36 + .../in/cargo-test-fixture.rs | 7 + .../cargo_add/script_frontmatter/mod.rs | 39 + .../out/cargo-test-fixture.rs | 10 + .../script_frontmatter/stderr.term.svg | 31 + .../script_shebang/in/cargo-test-fixture.rs | 3 + .../testsuite/cargo_add/script_shebang/mod.rs | 39 + .../script_shebang/out/cargo-test-fixture.rs | 7 + .../cargo_add/script_shebang/stderr.term.svg | 36 + .../sorted_table_with_dotted_item/mod.rs | 44 + .../stderr.term.svg | 39 + .../testsuite/cargo_add/target_cfg/mod.rs | 39 + .../cargo_add/target_cfg/stderr.term.svg | 33 + .../unknown_inherited_feature/mod.rs | 24 + .../unknown_inherited_feature/stderr.term.svg | 40 + .../tests/testsuite/cargo_add/vers/mod.rs | 37 + .../testsuite/cargo_add/vers/stderr.term.svg | 31 + .../testsuite/cargo_add/workspace_name/mod.rs | 38 + .../cargo_add/workspace_name/stderr.term.svg | 27 + .../testsuite/cargo_add/workspace_path/mod.rs | 38 + .../cargo_add/workspace_path/stderr.term.svg | 27 + .../cargo_add/workspace_path_dev/mod.rs | 38 + .../workspace_path_dev/stderr.term.svg | 27 + .../tests/testsuite/cargo_add/yanked/mod.rs | 31 + .../cargo_add/yanked/stderr.term.svg | 31 + .../tests/testsuite/cargo_alias_config.rs | 497 ++ .../tests/testsuite/cargo_bench/help/mod.rs | 14 + .../cargo_bench/help/stdout.term.svg | 146 + .../tests/testsuite/cargo_bench/mod.rs | 2 + .../cargo_bench/no_keep_going/mod.rs | 22 + .../cargo_bench/no_keep_going/stderr.term.svg | 42 + .../tests/testsuite/cargo_build/help/mod.rs | 14 + .../cargo_build/help/stdout.term.svg | 144 + .../tests/testsuite/cargo_build/mod.rs | 1 + .../tests/testsuite/cargo_check/help/mod.rs | 14 + .../cargo_check/help/stdout.term.svg | 140 + .../tests/testsuite/cargo_check/mod.rs | 1 + .../tests/testsuite/cargo_clean/help/mod.rs | 14 + .../cargo_clean/help/stdout.term.svg | 90 + .../tests/testsuite/cargo_clean/mod.rs | 1 + .../tests/testsuite/cargo_command.rs | 572 ++ .../tests/testsuite/cargo_config/help/mod.rs | 14 + .../cargo_config/help/stdout.term.svg | 66 + .../tests/testsuite/cargo_config/mod.rs | 580 ++ .../tests/testsuite/cargo_doc/help/mod.rs | 14 + .../testsuite/cargo_doc/help/stdout.term.svg | 134 + .../tests/testsuite/cargo_doc/mod.rs | 1 + .../tests/testsuite/cargo_env_config.rs | 443 + .../tests/testsuite/cargo_features.rs | 710 ++ .../tests/testsuite/cargo_fetch/help/mod.rs | 14 + .../cargo_fetch/help/stdout.term.svg | 74 + .../tests/testsuite/cargo_fetch/mod.rs | 1 + .../tests/testsuite/cargo_fix/help/mod.rs | 14 + .../testsuite/cargo_fix/help/stdout.term.svg | 150 + .../tests/testsuite/cargo_fix/mod.rs | 1 + .../cargo_generate_lockfile/help/mod.rs | 14 + .../help/stdout.term.svg | 70 + .../testsuite/cargo_generate_lockfile/mod.rs | 1 + .../testsuite/cargo_git_checkout/help/mod.rs | 14 + .../cargo_git_checkout/help/stdout.term.svg | 25 + .../tests/testsuite/cargo_git_checkout/mod.rs | 1 + .../tests/testsuite/cargo_help/help/mod.rs | 14 + .../testsuite/cargo_help/help/stdout.term.svg | 66 + .../tests/testsuite/cargo_help/mod.rs | 1 + .../tests/testsuite/cargo_info/basic/mod.rs | 53 + .../cargo_info/basic/stderr.term.svg | 31 + .../cargo_info/basic/stdout.term.svg | 51 + .../testsuite/cargo_info/features/mod.rs | 23 + .../cargo_info/features/stderr.term.svg | 31 + .../cargo_info/features/stdout.term.svg | 44 + .../features_activated_over_limit/mod.rs | 36 + .../stderr.term.svg | 31 + .../stdout.term.svg | 43 + .../mod.rs | 37 + .../stderr.term.svg | 31 + .../stdout.term.svg | 441 + .../features_deactivated_over_limit/mod.rs | 36 + .../stderr.term.svg | 31 + .../stdout.term.svg | 83 + .../cargo_info/git_dependency/mod.rs | 44 + .../cargo_info/git_dependency/stdout.term.svg | 40 + .../tests/testsuite/cargo_info/help/mod.rs | 13 + .../testsuite/cargo_info/help/stdout.term.svg | 74 + .../tests/testsuite/cargo_info/mod.rs | 39 + .../testsuite/cargo_info/not_found/mod.rs | 24 + .../cargo_info/not_found/stderr.term.svg | 30 + .../cargo_info/path_dependency/mod.rs | 24 + .../path_dependency/stdout.term.svg | 40 + .../pick_msrv_compatible_package/mod.rs | 24 + .../stderr.term.svg | 31 + .../stdout.term.svg | 36 + .../mod.rs | 32 + .../stderr.term.svg | 31 + .../stdout.term.svg | 36 + .../mod.rs | 32 + .../stderr.term.svg | 31 + .../stdout.term.svg | 36 + .../specify_empty_version_with_url/mod.rs | 22 + .../stderr.term.svg | 33 + .../specify_version_outside_ws/mod.rs | 20 + .../stderr.term.svg | 31 + .../stdout.term.svg | 36 + .../mod.rs | 22 + .../stderr.term.svg | 30 + .../mod.rs | 36 + .../stderr.term.svg | 31 + .../stdout.term.svg | 36 + .../mod.rs | 36 + .../stderr.term.svg | 34 + .../stdout.term.svg | 39 + .../direct1-stderr.term.svg | 32 + .../direct1-stdout.term.svg | 39 + .../direct2-stderr.term.svg | 27 + .../direct2-stdout.term.svg | 39 + .../transitive_dependency_within_ws/mod.rs | 78 + .../transitive1-stderr.term.svg | 27 + .../transitive1-stdout.term.svg | 39 + .../transitive2-stderr.term.svg | 27 + .../transitive2-stdout.term.svg | 39 + .../ws-stderr.term.svg | 34 + .../ws-stdout.term.svg | 39 + .../tests/testsuite/cargo_info/verbose/mod.rs | 53 + .../cargo_info/verbose/stderr.term.svg | 31 + .../cargo_info/verbose/stdout.term.svg | 59 + .../cargo_info/with_frozen_outside_ws/mod.rs | 30 + .../with_frozen_outside_ws/stderr.term.svg | 27 + .../cargo_info/with_frozen_within_ws/mod.rs | 37 + .../with_frozen_within_ws/stderr.term.svg | 27 + .../cargo_info/with_locked_outside_ws/mod.rs | 30 + .../with_locked_outside_ws/stderr.term.svg | 27 + .../cargo_info/with_locked_within_ws/mod.rs | 37 + .../with_locked_within_ws/stderr.term.svg | 30 + .../mod.rs | 37 + .../stderr.term.svg | 31 + .../stdout.term.svg | 36 + .../testsuite/cargo_info/with_offline/mod.rs | 30 + .../cargo_info/with_offline/stderr.term.svg | 27 + .../testsuite/cargo_info/with_quiet/mod.rs | 30 + .../cargo_info/with_quiet/stdout.term.svg | 36 + .../testsuite/cargo_info/within_ws/mod.rs | 36 + .../cargo_info/within_ws/stderr.term.svg | 34 + .../cargo_info/within_ws/stdout.term.svg | 39 + .../within_ws_and_pick_ws_package/mod.rs | 27 + .../stdout.term.svg | 36 + .../mod.rs | 30 + .../stderr.term.svg | 33 + .../stdout.term.svg | 36 + .../within_ws_without_lockfile/mod.rs | 33 + .../stderr.term.svg | 39 + .../stdout.term.svg | 39 + .../without_requiring_registry_auth/mod.rs | 26 + .../stderr.term.svg | 34 + .../stdout.term.svg | 39 + .../testsuite/cargo_init/auto_git/in/mod.rs | 7 + .../testsuite/cargo_init/auto_git/mod.rs | 23 + .../cargo_init/auto_git/stderr.term.svg | 30 + .../in/src/main.rs | 4 + .../bin_already_exists_explicit/mod.rs | 22 + .../stderr.term.svg | 30 + .../in/main.rs | 4 + .../bin_already_exists_explicit_nosrc/mod.rs | 23 + .../stderr.term.svg | 30 + .../in/src/main.rs | 4 + .../bin_already_exists_implicit/mod.rs | 22 + .../stderr.term.svg | 30 + .../in/case.rs | 4 + .../mod.rs | 23 + .../stderr.term.svg | 30 + .../in/src/case.rs | 4 + .../mod.rs | 23 + .../stderr.term.svg | 30 + .../in/main.rs | 4 + .../bin_already_exists_implicit_nosrc/mod.rs | 23 + .../stderr.term.svg | 30 + .../cargo_init/both_lib_and_bin/mod.rs | 19 + .../both_lib_and_bin/stderr.term.svg | 27 + .../in/case.rs | 1 + .../in/lib.rs | 1 + .../mod.rs | 19 + .../stderr.term.svg | 30 + .../confused_by_multiple_lib_files/in/lib.rs | 1 + .../in/src/lib.rs | 1 + .../confused_by_multiple_lib_files/mod.rs | 23 + .../confused_by_multiple_lib_files/out/lib.rs | 1 + .../out/src/lib.rs | 1 + .../stderr.term.svg | 27 + .../in/case.rs | 1 + .../in/lib.rs | 1 + .../mod.rs | 22 + .../stderr.term.svg | 30 + .../in/case.rs | 1 + .../mod.rs | 22 + .../stderr.term.svg | 33 + .../in/case.rs | 1 + .../mod.rs | 22 + .../stderr.term.svg | 33 + .../testsuite/cargo_init/empty_dir/mod.rs | 7 + .../explicit_bin_with_git/in/mod.rs | 7 + .../cargo_init/explicit_bin_with_git/mod.rs | 22 + .../explicit_bin_with_git/stderr.term.svg | 30 + .../cargo_init/formats_source/in/rustfmt.toml | 1 + .../cargo_init/formats_source/mod.rs | 30 + .../cargo_init/formats_source/stderr.term.svg | 30 + .../fossil_autodetect/in/.fossil/.keep | 0 .../cargo_init/fossil_autodetect/mod.rs | 23 + .../fossil_autodetect/stderr.term.svg | 30 + .../cargo_init/git_autodetect/mod.rs | 25 + .../cargo_init/git_autodetect/stderr.term.svg | 30 + .../in/.gitignore | 1 + .../mod.rs | 23 + .../stderr.term.svg | 30 + .../tests/testsuite/cargo_init/help/mod.rs | 14 + .../testsuite/cargo_init/help/stdout.term.svg | 88 + .../in/rustfmt.toml | 1 + .../ignores_failure_to_format_source/mod.rs | 23 + .../stderr.term.svg | 30 + .../inferred_bin_with_git/in/main.rs | 1 + .../cargo_init/inferred_bin_with_git/mod.rs | 22 + .../inferred_bin_with_git/stderr.term.svg | 30 + .../inferred_lib_with_git/in/lib.rs | 1 + .../cargo_init/inferred_lib_with_git/mod.rs | 22 + .../inferred_lib_with_git/stderr.term.svg | 30 + .../inherit_workspace_package_table/mod.rs | 25 + .../stderr.term.svg | 30 + .../cargo_init/invalid_dir_name/mod.rs | 21 + .../invalid_dir_name/stderr.term.svg | 44 + .../lib_already_exists_nosrc/in/lib.rs | 0 .../lib_already_exists_nosrc/mod.rs | 23 + .../lib_already_exists_nosrc/stderr.term.svg | 30 + .../lib_already_exists_src/in/src/lib.rs | 1 + .../cargo_init/lib_already_exists_src/mod.rs | 23 + .../lib_already_exists_src/stderr.term.svg | 30 + .../mercurial_autodetect/in/.hg/.keep | 0 .../cargo_init/mercurial_autodetect/mod.rs | 23 + .../mercurial_autodetect/stderr.term.svg | 30 + .../tests/testsuite/cargo_init/mod.rs | 45 + .../multibin_project_name_clash/in/case.rs | 1 + .../multibin_project_name_clash/in/main.rs | 1 + .../multibin_project_name_clash/mod.rs | 23 + .../multibin_project_name_clash/out/case.rs | 1 + .../multibin_project_name_clash/out/main.rs | 1 + .../stderr.term.svg | 33 + .../testsuite/cargo_init/no_filename/mod.rs | 16 + .../cargo_init/no_filename/stderr.term.svg | 27 + .../path_contains_separator/in/.keep | 0 .../cargo_init/path_contains_separator/mod.rs | 27 + .../path_contains_separator/stderr.term.svg | 35 + .../pijul_autodetect/in/.pijul/.keep | 0 .../cargo_init/pijul_autodetect/mod.rs | 23 + .../pijul_autodetect/stderr.term.svg | 30 + .../testsuite/cargo_init/reserved_name/mod.rs | 22 + .../cargo_init/reserved_name/stderr.term.svg | 44 + .../testsuite/cargo_init/simple_bin/in/mod.rs | 7 + .../testsuite/cargo_init/simple_bin/mod.rs | 30 + .../cargo_init/simple_bin/stderr.term.svg | 30 + .../testsuite/cargo_init/simple_git/in/mod.rs | 7 + .../testsuite/cargo_init/simple_git/mod.rs | 23 + .../cargo_init/simple_git/stderr.term.svg | 30 + .../simple_git_ignore_exists/in/.gitignore | 2 + .../simple_git_ignore_exists/mod.rs | 29 + .../simple_git_ignore_exists/stderr.term.svg | 30 + .../testsuite/cargo_init/simple_hg/in/mod.rs | 7 + .../testsuite/cargo_init/simple_hg/mod.rs | 23 + .../cargo_init/simple_hg/stderr.term.svg | 30 + .../simple_hg_ignore_exists/in/.hg/.keep | 0 .../simple_hg_ignore_exists/in/.hgignore | 1 + .../cargo_init/simple_hg_ignore_exists/mod.rs | 23 + .../simple_hg_ignore_exists/stderr.term.svg | 30 + .../testsuite/cargo_init/simple_lib/in/mod.rs | 7 + .../testsuite/cargo_init/simple_lib/mod.rs | 30 + .../cargo_init/simple_lib/stderr.term.svg | 30 + .../testsuite/cargo_init/unknown_flags/mod.rs | 15 + .../cargo_init/unknown_flags/stderr.term.svg | 42 + .../cargo_init/with_argument/in/foo/.keep | 0 .../testsuite/cargo_init/with_argument/mod.rs | 22 + .../cargo_init/with_argument/stderr.term.svg | 30 + .../cargo_init/workspace_add_member/mod.rs | 22 + .../workspace_add_member/stderr.term.svg | 32 + .../tests/testsuite/cargo_install/help/mod.rs | 14 + .../cargo_install/help/stdout.term.svg | 144 + .../tests/testsuite/cargo_install/mod.rs | 1 + .../cargo_locate_project/help/mod.rs | 14 + .../cargo_locate_project/help/stdout.term.svg | 70 + .../testsuite/cargo_locate_project/mod.rs | 1 + .../tests/testsuite/cargo_login/help/mod.rs | 14 + .../cargo_login/help/stdout.term.svg | 72 + .../tests/testsuite/cargo_login/mod.rs | 1 + .../tests/testsuite/cargo_logout/help/mod.rs | 14 + .../cargo_logout/help/stdout.term.svg | 66 + .../tests/testsuite/cargo_logout/mod.rs | 1 + .../testsuite/cargo_metadata/help/mod.rs | 14 + .../cargo_metadata/help/stdout.term.svg | 88 + .../tests/testsuite/cargo_metadata/mod.rs | 1 + .../add_members_to_non_workspace/mod.rs | 25 + .../stderr.term.svg | 30 + .../mod.rs | 25 + .../stderr.term.svg | 32 + .../mod.rs | 25 + .../stderr.term.svg | 32 + .../mod.rs | 26 + .../stderr.term.svg | 32 + .../mod.rs | 25 + .../stderr.term.svg | 32 + .../mod.rs | 25 + .../stderr.term.svg | 30 + .../mod.rs | 25 + .../stderr.term.svg | 30 + .../mod.rs | 25 + .../stderr.term.svg | 32 + .../testsuite/cargo_new/empty_name/in/.keep | 0 .../testsuite/cargo_new/empty_name/mod.rs | 25 + .../testsuite/cargo_new/empty_name/out/.keep | 0 .../cargo_new/empty_name/stderr.term.svg | 30 + .../tests/testsuite/cargo_new/help/mod.rs | 14 + .../testsuite/cargo_new/help/stdout.term.svg | 88 + .../ignore_current_dir_workspace/mod.rs | 25 + .../stderr.term.svg | 30 + .../cargo_new/inherit_workspace_lints/mod.rs | 25 + .../inherit_workspace_lints/stderr.term.svg | 30 + .../inherit_workspace_package_table/mod.rs | 25 + .../stderr.term.svg | 30 + .../mod.rs | 25 + .../stderr.term.svg | 30 + .../mod.rs | 25 + .../stderr.term.svg | 30 + .../mod.rs | 25 + .../stderr.term.svg | 30 + .../tests/testsuite/cargo_new/mod.rs | 17 + .../mod.rs | 25 + .../stderr.term.svg | 30 + .../tests/testsuite/cargo_owner/help/mod.rs | 14 + .../cargo_owner/help/stdout.term.svg | 82 + .../tests/testsuite/cargo_owner/mod.rs | 1 + .../tests/testsuite/cargo_package/help/mod.rs | 14 + .../cargo_package/help/stdout.term.svg | 112 + .../tests/testsuite/cargo_package/mod.rs | 1 + .../tests/testsuite/cargo_pkgid/help/mod.rs | 14 + .../cargo_pkgid/help/stdout.term.svg | 80 + .../tests/testsuite/cargo_pkgid/mod.rs | 1 + .../tests/testsuite/cargo_publish/help/mod.rs | 14 + .../cargo_publish/help/stdout.term.svg | 112 + .../tests/testsuite/cargo_publish/mod.rs | 1 + .../testsuite/cargo_read_manifest/help/mod.rs | 14 + .../cargo_read_manifest/help/stdout.term.svg | 66 + .../testsuite/cargo_read_manifest/mod.rs | 1 + .../cargo_remove/avoid_empty_tables/mod.rs | 38 + .../avoid_empty_tables/stderr.term.svg | 27 + .../tests/testsuite/cargo_remove/build/mod.rs | 38 + .../cargo_remove/build/stderr.term.svg | 27 + .../tests/testsuite/cargo_remove/dev/mod.rs | 38 + .../cargo_remove/dev/stderr.term.svg | 27 + .../testsuite/cargo_remove/dry_run/mod.rs | 38 + .../cargo_remove/dry_run/stderr.term.svg | 30 + .../cargo_remove/gc_keep_used_patch/mod.rs | 30 + .../gc_keep_used_patch/stderr.term.svg | 27 + .../testsuite/cargo_remove/gc_patch/mod.rs | 81 + .../cargo_remove/gc_patch/stderr.term.svg | 27 + .../testsuite/cargo_remove/gc_profile/mod.rs | 39 + .../cargo_remove/gc_profile/stderr.term.svg | 27 + .../testsuite/cargo_remove/gc_replace/mod.rs | 39 + .../cargo_remove/gc_replace/stderr.term.svg | 27 + .../tests/testsuite/cargo_remove/help/mod.rs | 14 + .../cargo_remove/help/stdout.term.svg | 92 + .../testsuite/cargo_remove/invalid_arg/mod.rs | 38 + .../cargo_remove/invalid_arg/stderr.term.svg | 42 + .../testsuite/cargo_remove/invalid_dep/mod.rs | 36 + .../cargo_remove/invalid_dep/stderr.term.svg | 30 + .../cargo_remove/invalid_package/mod.rs | 40 + .../invalid_package/stderr.term.svg | 27 + .../invalid_package_multiple/mod.rs | 40 + .../invalid_package_multiple/stderr.term.svg | 29 + .../cargo_remove/invalid_section/mod.rs | 38 + .../invalid_section/stderr.term.svg | 30 + .../cargo_remove/invalid_section_dep/mod.rs | 38 + .../invalid_section_dep/stderr.term.svg | 30 + .../cargo_remove/invalid_target/mod.rs | 40 + .../invalid_target/stderr.term.svg | 30 + .../cargo_remove/invalid_target_dep/mod.rs | 40 + .../invalid_target_dep/stderr.term.svg | 30 + .../testsuite/cargo_remove/last_dep/mod.rs | 28 + .../cargo_remove/last_dep/stderr.term.svg | 27 + .../tests/testsuite/cargo_remove/mod.rs | 37 + .../cargo_remove/multiple_deps/mod.rs | 38 + .../multiple_deps/stderr.term.svg | 29 + .../cargo_remove/multiple_dev/mod.rs | 38 + .../cargo_remove/multiple_dev/stderr.term.svg | 29 + .../testsuite/cargo_remove/no_arg/mod.rs | 37 + .../cargo_remove/no_arg/stderr.term.svg | 39 + .../testsuite/cargo_remove/offline/mod.rs | 45 + .../cargo_remove/offline/stderr.term.svg | 27 + .../cargo_remove/optional_dep_feature/mod.rs | 38 + .../optional_dep_feature/stderr.term.svg | 27 + .../optional_dep_feature_formatting/mod.rs | 38 + .../stderr.term.svg | 29 + .../cargo_remove/optional_feature/mod.rs | 38 + .../optional_feature/stderr.term.svg | 27 + .../testsuite/cargo_remove/package/mod.rs | 40 + .../cargo_remove/package/stderr.term.svg | 27 + .../cargo_remove/remove_basic/mod.rs | 38 + .../cargo_remove/remove_basic/stderr.term.svg | 27 + .../script/in/cargo-remove-test-fixture.rs | 23 + .../testsuite/cargo_remove/script/mod.rs | 40 + .../script/out/cargo-remove-test-fixture.rs | 22 + .../cargo_remove/script/stderr.term.svg | 32 + .../in/cargo-remove-test-fixture.rs | 7 + .../testsuite/cargo_remove/script_last/mod.rs | 30 + .../out/cargo-remove-test-fixture.rs | 6 + .../cargo_remove/script_last/stderr.term.svg | 32 + .../cargo_remove/skip_gc_glob_profile/mod.rs | 28 + .../skip_gc_glob_profile/stderr.term.svg | 27 + .../cargo_remove/target_build/mod.rs | 40 + .../cargo_remove/target_build/stderr.term.svg | 27 + .../testsuite/cargo_remove/target_dev/mod.rs | 40 + .../cargo_remove/target_dev/stderr.term.svg | 27 + .../cargo_remove/update_lock_file/mod.rs | 38 + .../update_lock_file/stderr.term.svg | 27 + .../testsuite/cargo_remove/workspace/mod.rs | 38 + .../cargo_remove/workspace/stderr.term.svg | 27 + .../cargo_remove/workspace_non_virtual/mod.rs | 38 + .../workspace_non_virtual/stderr.term.svg | 27 + .../cargo_remove/workspace_preserved/mod.rs | 38 + .../workspace_preserved/stderr.term.svg | 27 + .../tests/testsuite/cargo_report/help/mod.rs | 14 + .../cargo_report/help/stdout.term.svg | 70 + .../tests/testsuite/cargo_report/mod.rs | 1 + .../tests/testsuite/cargo_run/help/mod.rs | 14 + .../testsuite/cargo_run/help/stdout.term.svg | 122 + .../tests/testsuite/cargo_run/mod.rs | 1 + .../tests/testsuite/cargo_rustc/help/mod.rs | 14 + .../cargo_rustc/help/stdout.term.svg | 144 + .../tests/testsuite/cargo_rustc/mod.rs | 1 + .../tests/testsuite/cargo_rustdoc/help/mod.rs | 14 + .../cargo_rustdoc/help/stdout.term.svg | 142 + .../tests/testsuite/cargo_rustdoc/mod.rs | 1 + .../tests/testsuite/cargo_search/help/mod.rs | 14 + .../cargo_search/help/stdout.term.svg | 76 + .../tests/testsuite/cargo_search/mod.rs | 1 + .../tests/testsuite/cargo_targets.rs | 72 + .../tests/testsuite/cargo_test/help/mod.rs | 14 + .../testsuite/cargo_test/help/stdout.term.svg | 154 + .../tests/testsuite/cargo_test/mod.rs | 2 + .../testsuite/cargo_test/no_keep_going/mod.rs | 22 + .../cargo_test/no_keep_going/stderr.term.svg | 42 + .../tests/testsuite/cargo_tree/help/mod.rs | 14 + .../testsuite/cargo_tree/help/stdout.term.svg | 118 + .../tests/testsuite/cargo_tree/mod.rs | 1 + .../testsuite/cargo_uninstall/help/mod.rs | 14 + .../cargo_uninstall/help/stdout.term.svg | 84 + .../tests/testsuite/cargo_uninstall/mod.rs | 1 + .../tests/testsuite/cargo_update/help/mod.rs | 14 + .../cargo_update/help/stdout.term.svg | 86 + .../tests/testsuite/cargo_update/mod.rs | 2 + .../cargo_update/toolchain_pkgname/mod.rs | 21 + .../toolchain_pkgname/stderr.term.svg | 29 + .../tests/testsuite/cargo_vendor/help/mod.rs | 14 + .../cargo_vendor/help/stdout.term.svg | 82 + .../tests/testsuite/cargo_vendor/mod.rs | 1 + .../cargo_verify_project/help/mod.rs | 14 + .../cargo_verify_project/help/stdout.term.svg | 66 + .../testsuite/cargo_verify_project/mod.rs | 1 + .../tests/testsuite/cargo_version/help/mod.rs | 14 + .../cargo_version/help/stdout.term.svg | 64 + .../tests/testsuite/cargo_version/mod.rs | 1 + .../tests/testsuite/cargo_yank/help/mod.rs | 14 + .../testsuite/cargo_yank/help/stdout.term.svg | 80 + .../tests/testsuite/cargo_yank/mod.rs | 1 + .../cargo-0.87.1/tests/testsuite/cfg.rs | 661 ++ .../cargo-0.87.1/tests/testsuite/check.rs | 1664 ++++ .../cargo-0.87.1/tests/testsuite/check_cfg.rs | 931 +++ .../cargo-0.87.1/tests/testsuite/clean.rs | 921 +++ .../tests/testsuite/collisions.rs | 593 ++ .../tests/testsuite/concurrent.rs | 510 ++ .../cargo-0.87.1/tests/testsuite/config.rs | 2275 ++++++ .../tests/testsuite/config_cli.rs | 577 ++ .../tests/testsuite/config_include.rs | 495 ++ .../tests/testsuite/corrupt_git.rs | 161 + .../tests/testsuite/credential_process.rs | 769 ++ .../tests/testsuite/cross_compile.rs | 1301 +++ .../tests/testsuite/cross_publish.rs | 123 + .../tests/testsuite/custom_target.rs | 268 + .../cargo-0.87.1/tests/testsuite/death.rs | 102 + .../cargo-0.87.1/tests/testsuite/dep_info.rs | 554 ++ .../tests/testsuite/diagnostics.rs | 33 + .../testsuite/direct_minimal_versions.rs | 256 + .../cargo-0.87.1/tests/testsuite/directory.rs | 866 ++ .../cargo-0.87.1/tests/testsuite/doc.rs | 2899 +++++++ .../cargo-0.87.1/tests/testsuite/docscrape.rs | 770 ++ .../cargo-0.87.1/tests/testsuite/edition.rs | 196 + .../cargo-0.87.1/tests/testsuite/error.rs | 21 + .../tests/testsuite/feature_unification.rs | 205 + .../cargo-0.87.1/tests/testsuite/features.rs | 2284 ++++++ .../cargo-0.87.1/tests/testsuite/features2.rs | 2818 +++++++ .../tests/testsuite/features_namespaced.rs | 1369 ++++ .../cargo-0.87.1/tests/testsuite/fetch.rs | 146 + .../cargo-0.87.1/tests/testsuite/fix.rs | 2869 +++++++ .../tests/testsuite/fix_n_times.rs | 522 ++ .../cargo-0.87.1/tests/testsuite/freshness.rs | 3184 ++++++++ .../tests/testsuite/freshness_checksum.rs | 2963 +++++++ .../tests/testsuite/future_incompat_report.rs | 453 ++ .../tests/testsuite/generate_lockfile.rs | 286 + .../cargo-0.87.1/tests/testsuite/git.rs | 4262 ++++++++++ .../cargo-0.87.1/tests/testsuite/git_auth.rs | 480 ++ .../cargo-0.87.1/tests/testsuite/git_gc.rs | 117 + .../tests/testsuite/git_shallow.rs | 860 ++ .../tests/testsuite/glob_targets.rs | 512 ++ .../tests/testsuite/global_cache_tracker.rs | 2141 +++++ .../cargo-0.87.1/tests/testsuite/help.rs | 159 + .../cargo-0.87.1/tests/testsuite/https.rs | 165 + .../testsuite/inheritable_workspace_fields.rs | 1920 +++++ .../cargo-0.87.1/tests/testsuite/install.rs | 2887 +++++++ .../tests/testsuite/install_upgrade.rs | 986 +++ .../cargo-0.87.1/tests/testsuite/jobserver.rs | 412 + .../tests/testsuite/lints/error/mod.rs | 36 + .../testsuite/lints/error/stderr.term.svg | 41 + .../tests/testsuite/lints/inherited/mod.rs | 43 + .../testsuite/lints/inherited/stderr.term.svg | 57 + .../cargo-0.87.1/tests/testsuite/lints/mod.rs | 326 + .../tests/testsuite/lints/unknown_lints.rs | 91 + .../tests/testsuite/lints/warning/mod.rs | 36 + .../testsuite/lints/warning/stderr.term.svg | 46 + .../tests/testsuite/lints_table.rs | 843 ++ .../tests/testsuite/list_availables.rs | 1005 +++ .../tests/testsuite/local_registry.rs | 554 ++ .../tests/testsuite/locate_project.rs | 125 + .../tests/testsuite/lockfile_compat.rs | 1311 +++ .../tests/testsuite/lockfile_path.rs | 556 ++ .../cargo-0.87.1/tests/testsuite/login.rs | 388 + .../cargo-0.87.1/tests/testsuite/logout.rs | 129 + .../cargo-0.87.1/tests/testsuite/lto.rs | 945 +++ .../cargo-0.87.1/tests/testsuite/main.rs | 198 + .../tests/testsuite/member_discovery.rs | 44 + .../tests/testsuite/member_errors.rs | 168 + .../tests/testsuite/message_format.rs | 164 + .../cargo-0.87.1/tests/testsuite/messages.rs | 164 + .../cargo-0.87.1/tests/testsuite/metabuild.rs | 829 ++ .../cargo-0.87.1/tests/testsuite/metadata.rs | 4956 ++++++++++++ .../tests/testsuite/minimal_versions.rs | 46 + .../tests/testsuite/multitarget.rs | 270 + .../tests/testsuite/net_config.rs | 78 + .../cargo-0.87.1/tests/testsuite/new.rs | 571 ++ .../cargo-0.87.1/tests/testsuite/offline.rs | 788 ++ .../tests/testsuite/old_cargos.rs | 741 ++ .../tests/testsuite/open_namespaces.rs | 460 ++ .../cargo-0.87.1/tests/testsuite/owner.rs | 194 + .../cargo-0.87.1/tests/testsuite/package.rs | 7192 +++++++++++++++++ .../tests/testsuite/package_features.rs | 994 +++ .../cargo-0.87.1/tests/testsuite/patch.rs | 3147 ++++++++ .../cargo-0.87.1/tests/testsuite/path.rs | 1922 +++++ .../cargo-0.87.1/tests/testsuite/paths.rs | 252 + .../cargo-0.87.1/tests/testsuite/pgo.rs | 112 + .../cargo-0.87.1/tests/testsuite/pkgid.rs | 407 + .../tests/testsuite/precise_pre_release.rs | 189 + .../tests/testsuite/proc_macro.rs | 570 ++ .../tests/testsuite/profile_config.rs | 526 ++ .../tests/testsuite/profile_custom.rs | 701 ++ .../tests/testsuite/profile_overrides.rs | 611 ++ .../tests/testsuite/profile_targets.rs | 733 ++ .../tests/testsuite/profile_trim_paths.rs | 851 ++ .../cargo-0.87.1/tests/testsuite/profiles.rs | 878 ++ .../cargo-0.87.1/tests/testsuite/progress.rs | 167 + .../cargo-0.87.1/tests/testsuite/pub_priv.rs | 684 ++ .../cargo-0.87.1/tests/testsuite/publish.rs | 4113 ++++++++++ .../tests/testsuite/publish_lockfile.rs | 591 ++ .../tests/testsuite/read_manifest.rs | 236 + .../cargo-0.87.1/tests/testsuite/registry.rs | 4615 +++++++++++ .../tests/testsuite/registry_auth.rs | 575 ++ .../tests/testsuite/registry_overlay.rs | 306 + .../tests/testsuite/rename_deps.rs | 406 + .../cargo-0.87.1/tests/testsuite/replace.rs | 1500 ++++ .../tests/testsuite/required_features.rs | 1630 ++++ .../cargo-0.87.1/tests/testsuite/run.rs | 1744 ++++ .../tests/testsuite/rust_version.rs | 1072 +++ .../cargo-0.87.1/tests/testsuite/rustc.rs | 857 ++ .../tests/testsuite/rustc_info_cache.rs | 188 + .../cargo-0.87.1/tests/testsuite/rustdoc.rs | 322 + .../tests/testsuite/rustdoc_extern_html.rs | 497 ++ .../tests/testsuite/rustdocflags.rs | 281 + .../cargo-0.87.1/tests/testsuite/rustflags.rs | 1792 ++++ .../cargo-0.87.1/tests/testsuite/rustup.rs | 261 + .../cargo-0.87.1/tests/testsuite/script.rs | 1888 +++++ .../cargo-0.87.1/tests/testsuite/search.rs | 226 + .../tests/testsuite/shell_quoting.rs | 43 + .../tests/testsuite/source_replacement.rs | 339 + .../cargo-0.87.1/tests/testsuite/ssh.rs | 635 ++ .../tests/testsuite/standard_lib.rs | 872 ++ .../cargo-0.87.1/tests/testsuite/test.rs | 5591 +++++++++++++ .../cargo-0.87.1/tests/testsuite/timings.rs | 56 + .../tests/testsuite/tool_paths.rs | 487 ++ .../cargo-0.87.1/tests/testsuite/tree.rs | 2187 +++++ .../tests/testsuite/tree_graph_features.rs | 352 + .../tests/testsuite/unit_graph.rs | 236 + .../cargo-0.87.1/tests/testsuite/update.rs | 2711 +++++++ .../cargo-0.87.1/tests/testsuite/vendor.rs | 1941 +++++ .../tests/testsuite/verify_project.rs | 85 + .../cargo-0.87.1/tests/testsuite/version.rs | 70 + .../tests/testsuite/warn_on_failure.rs | 125 + .../tests/testsuite/warning_override.rs | 221 + .../tests/testsuite/weak_dep_features.rs | 668 ++ .../tests/testsuite/workspaces.rs | 2718 +++++++ .../cargo-0.87.1/tests/testsuite/yank.rs | 214 + .../cargo-0.87.1/triagebot.toml | 363 + .../cargo-0.87.1/windows.manifest.xml | 28 + 1455 files changed, 340117 insertions(+) create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.cargo/config.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.cargo_vcs_info.json create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/config.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/tracking_issue.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/renovate.json5 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/workflows/audit.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/workflows/contrib.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/workflows/main.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.github/workflows/release.yml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.gitignore create mode 100644 collector/compile-benchmarks/cargo-0.87.1/.ignore create mode 100644 collector/compile-benchmarks/cargo-0.87.1/CHANGELOG.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/CODE_OF_CONDUCT.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/CONTRIBUTING.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/Cargo.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/Cargo.toml.orig create mode 100644 collector/compile-benchmarks/cargo-0.87.1/LICENSE-APACHE create mode 100644 collector/compile-benchmarks/cargo-0.87.1/LICENSE-MIT create mode 100644 collector/compile-benchmarks/cargo-0.87.1/LICENSE-THIRD-PARTY create mode 100644 collector/compile-benchmarks/cargo-0.87.1/README.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/README.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/cargo.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/diem.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/empty.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/gecko-dev.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/rust-ws-inherit.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/rust.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/servo.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/substrate.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/tikv.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/toml-rs.tgz create mode 100644 collector/compile-benchmarks/cargo-0.87.1/build.rs create mode 100755 collector/compile-benchmarks/cargo-0.87.1/ci/clean-test-output.sh create mode 100755 collector/compile-benchmarks/cargo-0.87.1/ci/dump-environment.sh create mode 100755 collector/compile-benchmarks/cargo-0.87.1/ci/fetch-smoke-test.sh create mode 100644 collector/compile-benchmarks/cargo-0.87.1/ci/generate.py create mode 100755 collector/compile-benchmarks/cargo-0.87.1/ci/validate-man.sh create mode 100755 collector/compile-benchmarks/cargo-0.87.1/ci/validate-version-bump.sh create mode 100644 collector/compile-benchmarks/cargo-0.87.1/clippy.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/credential/README.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/deny.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/perf-config.json create mode 100755 collector/compile-benchmarks/cargo-0.87.1/publish.py create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/cli.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/add.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/bench.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/build.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/check.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/clean.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/doc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fetch.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fix.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/generate_lockfile.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/git_checkout.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/help.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/info.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/init.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/install.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/locate_project.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/login.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/logout.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/metadata.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/new.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/owner.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/package.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/pkgid.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/publish.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/read_manifest.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/remove.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/report.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/run.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustdoc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/search.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/test.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/tree.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/uninstall.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/update.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/vendor.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/verify_project.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/version.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/yank.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/artifact.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/target_info.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_plan.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/compilation_files.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compilation.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compile_kind.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/crate_type.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/custom_build.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dep_info.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dirty_reason.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/future_incompat.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job_state.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/layout.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/links.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/lto.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/output_depinfo.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/rustdoc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/standard_lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.js create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/unit.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/unit_dependencies.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/unit_graph.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/dependency.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/gc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/global_cache_tracker.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/manifest.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/package.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/package_id.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/package_id_spec.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/profiles.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/registry.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/conflict_cache.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/context.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/dep_cache.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/encode.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/errors.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/resolve.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/types.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/resolver/version_prefs.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/shell.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/source_id.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/summary.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/workspace.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/macros.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_add/crate_spec.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_add/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_clean.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_compile/compile_filter.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_compile/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_compile/packages.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_compile/unit_generator.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_doc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_fetch.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_install.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_new.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_output_metadata.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_package/vcs.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_package/verify.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_pkgid.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_read_manifest.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_remove.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_run.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_test.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_uninstall.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/cargo_update.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/common_for_install_and_uninstall.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/fix.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/lockfile.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/info/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/info/view.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/login.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/logout.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/owner.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/publish.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/search.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/registry/yank.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/resolve.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/tree/format/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/tree/format/parse.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/tree/graph.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/tree/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/ops/vendor.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/directory.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/git/known_hosts.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/git/oxide.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/git/source.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/git/utils.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/overlay.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/path.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/registry/download.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/registry/http_remote.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/registry/index/cache.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/registry/index/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/registry/local.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/registry/remote.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/replaced.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/sources/source.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/auth/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/cache_lock.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/canonical_url.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/command_prelude.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/context/de.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/context/environment.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/context/key.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/context/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/context/path.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/context/target.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/context/value.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/counter.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/cpu.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/credential/adaptor.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/credential/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/credential/paseto.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/credential/process.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/credential/token.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/dependency_queue.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/diagnostic_server.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/edit_distance.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/errors.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/flock.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/graph.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/hasher.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/hex.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/hostname.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/important_paths.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/interning.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/into_url.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/into_url_with_base.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/io.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/job.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/lints.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/lockserver.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/machine_message.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/network/http.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/network/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/network/proxy.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/network/retry.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/network/sleep.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/progress.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/queue.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/restricted_names.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/rustc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/semver_eval_ext.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/semver_ext.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/sqlite.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/style.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/toml/embedded.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/toml/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/toml/targets.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/toml_mut/dependency.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/toml_mut/manifest.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/toml_mut/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/toml_mut/upgrade.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/vcs.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/util/workspace.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/cargo/version.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/.gitignore create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/README.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/book.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/README.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/book.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/SUMMARY.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/design.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/architecture.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/console.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/debugging.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/filesystem.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/formatting.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/packages.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/schemas.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/implementation/subcommands.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/issues.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/process/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/process/release.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/process/rfc.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/process/security.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/process/unstable.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/process/working-on-cargo.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/team.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/tests/crater.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/tests/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/tests/profiling.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/tests/running.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/contrib/src/tests/writing.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-add.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-bench.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-build.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-check.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-clean.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-doc.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-fetch.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-fix.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-generate-lockfile.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-help.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-info.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-init.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-install.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-locate-project.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-login.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-logout.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-metadata.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-new.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-owner.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-package.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-pkgid.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-publish.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-remove.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-report.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-run.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-rustc.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-rustdoc.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-search.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-test.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-tree.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-uninstall.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-update.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-vendor.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-version.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo-yank.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/cargo.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-add.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-bench.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-build.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-check.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-clean.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-doc.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-fetch.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-fix.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-generate-lockfile.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-help.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-info.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-init.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-install.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-locate-project.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-login.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-logout.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-metadata.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-new.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-owner.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-package.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-pkgid.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-publish.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-remove.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-report.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-run.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-rustc.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-rustdoc.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-search.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-test.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-tree.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-uninstall.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-update.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-vendor.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-version.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo-yank.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/generated_txt/cargo.txt create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/description-install-root.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/description-one-target.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-display.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-future-incompat.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-ignore-rust-version.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-jobs.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-keep-going.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-locked.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-lockfile-path.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-manifest-path.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-message-format.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-new.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-output-format.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-profile-legacy-check.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-profile.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-registry.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-release.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-target-dir.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-target-triple.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-targets-bin-auto-built.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-targets-lib-bin.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-targets.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-test.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-timings.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/options-token.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/section-environment.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/section-exit-status.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/section-features.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/section-options-common.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/section-options-package.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/man/includes/section-package-selection.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/CHANGELOG.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/SUMMARY.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/appendix/git-authentication.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/appendix/glossary.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/build-commands.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-add.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-bench.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-build.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-check.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-clean.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-clippy.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-doc.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-fetch.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-fix.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-fmt.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-generate-lockfile.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-help.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-info.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-init.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-install.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-locate-project.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-login.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-logout.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-metadata.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-miri.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-new.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-owner.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-package.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-pkgid.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-publish.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-remove.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-report.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-run.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-rustc.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-rustdoc.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-search.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-test.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-tree.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-uninstall.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-update.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-vendor.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-version.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo-yank.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/cargo.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/deprecated-and-removed.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/general-commands.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/manifest-commands.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/package-commands.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/commands/publishing-commands.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/faq.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/getting-started/first-steps.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/getting-started/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/getting-started/installation.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/cargo-home.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/cargo-toml-vs-cargo-lock.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/continuous-integration.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/creating-a-new-project.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/dependencies.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/project-layout.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/tests.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/why-cargo-exists.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/guide/working-on-an-existing-project.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/images/Cargo-Logo-Small.png create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/images/auth-level-acl.png create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/images/build-info.png create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/images/build-unit-time.png create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/images/cargo-concurrency-over-time.png create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/images/org-level-acl.png create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/images/winapi-features.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/build-cache.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/build-script-examples.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/build-scripts.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/cargo-targets.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/config.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/credential-provider-protocol.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/environment-variables.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/external-tools.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/features-examples.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/features.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/future-incompat-report.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/lints.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/manifest.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/overriding-dependencies.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/pkgid-spec.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/profiles.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/publishing.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registries.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-authentication.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-index.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-web-api.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/resolver.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/running-a-registry.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/rust-version.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/semver.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/source-replacement.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/specifying-dependencies.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/timings.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/unstable.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/workspaces.md create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/theme/favicon.png create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/doc/theme/head.hbs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/_cargo create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/cargo.bashcomp.sh create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-add.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-bench.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-build.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-check.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-clean.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-doc.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fetch.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fix.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-generate-lockfile.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-help.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-info.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-init.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-install.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-locate-project.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-login.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-logout.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-metadata.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-new.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-owner.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-package.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-pkgid.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-publish.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-remove.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-report.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-run.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustc.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustdoc.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-search.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-test.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-tree.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-uninstall.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-update.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-vendor.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-version.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-yank.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo.1 create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/build-std/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/advanced_env.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/alt_registry.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dep.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dir.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_manifest_path.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bench.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/binary_name.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_plan.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_env.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_extra_link_arg.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_lock.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_messages.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/in/.cargo/config.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/in/.cargo/config.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/in/.cargo/config.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/in/.cargo/config.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/quiet/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/in/cargo-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/out/cargo-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/in/cargo-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/out/cargo-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/in/cargo-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/out/cargo-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_alias_config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_command.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_env_config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/in/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/in/src/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/in/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/in/src/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/in/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/in/src/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/in/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/src/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/src/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/in/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/in/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/empty_dir/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/in/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/in/rustfmt.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/in/.fossil/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/in/.gitignore create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/in/rustfmt.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/in/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/in/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/in/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/in/src/lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/in/.hg/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/case.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/in/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/in/.pijul/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/in/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/in/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/in/.gitignore create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/in/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hg/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hgignore create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/in/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/in/foo/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/in/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/out/.keep create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/in/cargo-remove-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/out/cargo-remove-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/in/cargo-remove-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/out/cargo-remove-test-fixture.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_targets.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/stdout.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cfg.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check_cfg.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/clean.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/collisions.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/concurrent.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_cli.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_include.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/corrupt_git.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/credential_process.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_compile.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_publish.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/custom_target.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/death.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/dep_info.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/diagnostics.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/direct_minimal_versions.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/directory.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/doc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/docscrape.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/edition.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/error.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/feature_unification.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features2.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features_namespaced.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fetch.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix_n_times.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness_checksum.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/future_incompat_report.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/generate_lockfile.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_auth.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_gc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_shallow.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/glob_targets.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/global_cache_tracker.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/help.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/https.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/inheritable_workspace_fields.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install_upgrade.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/jobserver.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/unknown_lints.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/mod.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/stderr.term.svg create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints_table.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/list_availables.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/local_registry.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/locate_project.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_compat.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_path.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/login.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/logout.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lto.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/main.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_discovery.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_errors.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/message_format.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/messages.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metabuild.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metadata.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/minimal_versions.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/multitarget.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/net_config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/new.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/offline.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/old_cargos.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/open_namespaces.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/owner.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package_features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/patch.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/path.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/paths.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pgo.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pkgid.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/precise_pre_release.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/proc_macro.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_config.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_custom.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_overrides.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_targets.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_trim_paths.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profiles.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/progress.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pub_priv.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish_lockfile.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/read_manifest.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_auth.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_overlay.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rename_deps.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/replace.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/required_features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/run.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rust_version.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc_info_cache.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc_extern_html.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdocflags.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustflags.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustup.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/script.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/search.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/shell_quoting.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/source_replacement.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/ssh.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/standard_lib.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/test.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/timings.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tool_paths.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree_graph_features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/unit_graph.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/update.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/vendor.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/verify_project.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/version.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warn_on_failure.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warning_override.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/weak_dep_features.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/workspaces.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/yank.rs create mode 100644 collector/compile-benchmarks/cargo-0.87.1/triagebot.toml create mode 100644 collector/compile-benchmarks/cargo-0.87.1/windows.manifest.xml diff --git a/collector/compile-benchmarks/cargo-0.87.1/.cargo/config.toml b/collector/compile-benchmarks/cargo-0.87.1/.cargo/config.toml new file mode 100644 index 000000000..f1a267084 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.cargo/config.toml @@ -0,0 +1,10 @@ +[alias] +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 +# inside of the rust-lang/rust repo because it looks for the furthest-away `Cargo.toml` +CARGO_RUSTC_CURRENT_DIR = { value = "", relative = true } diff --git a/collector/compile-benchmarks/cargo-0.87.1/.cargo_vcs_info.json b/collector/compile-benchmarks/cargo-0.87.1/.cargo_vcs_info.json new file mode 100644 index 000000000..12c66f670 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "ab9915ce5d9de5e1f2fb3c10378a353ca88693f2" + }, + "path_in_vcs": "" +} \ No newline at end of file diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/bug_report.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..5cee9c65c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,43 @@ +name: Bug Report +description: Create a report to help us improve +labels: ["C-bug", "S-triage"] +body: + - type: markdown + attributes: + value: Thanks for filing a 🐛 bug report 😄! + - type: textarea + id: problem + attributes: + label: Problem + description: > + Please provide a clear and concise description of what the bug is, + including what currently happens and what you expected to happen. + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps + description: Please list the steps to reproduce the bug. + placeholder: | + 1. + 2. + 3. + - type: textarea + id: possible-solutions + attributes: + label: Possible Solution(s) + description: > + Not obligatory, but suggest a fix/reason for the bug, + or ideas how to implement the addition or change. + - type: textarea + id: notes + attributes: + label: Notes + description: Provide any additional notes that might be helpful. + - type: textarea + id: version + attributes: + label: Version + description: Please paste the output of running `cargo version --verbose`. + render: text diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/config.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..ed4289847 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,10 @@ +contact_links: + - name: Question + url: https://users.rust-lang.org + about: > + Got a question about Cargo? Ask the community on the user forum. + - name: Inspiring Idea + url: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo + about: > + Need more discussions with your next big idea? + Reach out the coummunity on the internals forum. diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/feature_request.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..e6ed547f8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,35 @@ +name: Feature Request +description: Suggest an idea for enhancing Cargo +labels: ["C-feature-request", "S-triage"] +body: + - type: markdown + attributes: + value: | + Thanks for filing a 🙋 feature request 😄! + + If the feature request is relatively small and already with a possible solution, this might be the place for you. + + If you are brewing a big feature that needs feedback from the community, [the internal forum] is the best fit, especially for pre-RFC. You can also talk the idea over with other developers in [#t-cargo Zulip stream]. + + [the internal forum]: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo/15 + [#t-cargo Zulip stream]: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo + - type: textarea + id: problem + attributes: + label: Problem + description: > + Please provide a clear description of your use case and the problem + this feature request is trying to solve. + validations: + required: true + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: > + Please provide a clear and concise description of what you want to happen. + - type: textarea + id: notes + attributes: + label: Notes + description: Provide any additional context or information that might be helpful. diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/tracking_issue.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/tracking_issue.yml new file mode 100644 index 000000000..d687db4e5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/ISSUE_TEMPLATE/tracking_issue.yml @@ -0,0 +1,50 @@ +name: Tracking Issue +description: A tracking issue for an accepted feature or RFC in Cargo. +title: "Tracking Issue for _FEATURE_NAME_" +labels: ["C-tracking-issue"] +body: + - type: markdown + attributes: + value: > + Thank you for creating a tracking issue! Tracking issues are for tracking an + accepted feature or RFC from implementation to stabilization. Please do not + file a tracking issue until the feature or RFC has been approved. + - type: textarea + id: summary + attributes: + label: Summary + description: Please provide a very brief summary of the feature. + value: | + RFC: [#NNNN](https://github.com/rust-lang/rfcs/pull/NNNN) + Original issue: #NNNN + Implementation: #NNNN + Documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#my-feature + + Please enter a short, one-sentence description here. + validations: + required: true + - type: textarea + id: unresolved + attributes: + label: Unresolved Issues + description: List issues that have not yet been resolved. + placeholder: | + * [ ] Make a list of any known implementation or design issues. + - type: textarea + id: future + attributes: + label: Future Extensions + description: > + An optional section where you can mention where the feature may be + extended in the future, but is explicitly not intended to + address. + - type: textarea + id: about + attributes: + label: About tracking issues + description: Please include this notice in the issue. + value: | + Tracking issues are used to record the overall progress of implementation. + They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. + A tracking issue is however *not* meant for large scale discussion, questions, or bug reports about a feature. + Instead, open a dedicated issue for the specific matter and add the relevant feature gate label. diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/PULL_REQUEST_TEMPLATE.md b/collector/compile-benchmarks/cargo-0.87.1/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..0d2c2180a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,36 @@ + diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/renovate.json5 b/collector/compile-benchmarks/cargo-0.87.1/.github/renovate.json5 new file mode 100644 index 000000000..afb26b7d3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/renovate.json5 @@ -0,0 +1,98 @@ +{ + schedule: [ + 'before 5am on the first day of the month', + ], + semanticCommits: 'enabled', + configMigration: true, + dependencyDashboard: true, + ignorePaths: [ + '**/tests/**', + ], + // See rust-lang/cargo#13546 and openssl/openssl#23376 for the exclusion + ignoreDeps: ['openssl', 'openssl-src', 'openssl-sys'], + customManagers: [ + { + customType: 'regex', + fileMatch: [ + 'Cargo.toml$', + ], + matchStrings: [ + '\\bMSRV:1\\b.*?(?\\d+\\.\\d+(\\.\\d+)?)', + '(?\\d+\\.\\d+(\\.\\d+)?).*?\\bMSRV:1\\b', + ], + depNameTemplate: 'MSRV:1', // Support 1 version of rustc + packageNameTemplate: 'rust-lang/rust', + datasourceTemplate: 'github-releases', + }, + { + customType: 'regex', + fileMatch: [ + 'Cargo.toml$', + ], + matchStrings: [ + '\\bMSRV:3\\b.*?(?\\d+\\.\\d+(\\.\\d+)?)', + '(?\\d+\\.\\d+(\\.\\d+)?).*?\\bMSRV:3\\b', + ], + depNameTemplate: 'MSRV:3', // Support 3 versions of rustc + packageNameTemplate: 'rust-lang/rust', + datasourceTemplate: 'github-releases', + }, + ], + packageRules: [ + { + commitMessageTopic: 'MSRV (1 version)', + matchManagers: [ + 'custom.regex', + ], + matchDepNames: [ + 'MSRV:1', + ], + extractVersion: '^(?\\d+\\.\\d+)', // Drop the patch version + schedule: [ + '* * * * *', + ], + groupName: 'msrv', + }, + { + commitMessageTopic: 'MSRV (3 versions)', + matchManagers: [ + 'custom.regex', + ], + matchDepNames: [ + 'MSRV:3', + ], + extractVersion: '^(?\\d+\\.\\d+)', // Drop the patch version + schedule: [ + '* * * * *', + ], + minimumReleaseAge: '85 days', // 2 releases back * 6 weeks per release * 7 days per week + 1 + internalChecksFilter: 'strict', + groupName: 'msrv', + }, + // Goals: + // - Rollup safe upgrades to reduce CI runner load + // - Have lockfile and manifest in-sync (implicit rules) + { + matchManagers: [ + 'cargo', + ], + matchCurrentVersion: '>=0.1.0', + matchUpdateTypes: [ + 'patch', + ], + automerge: false, + groupName: 'compatible', + }, + { + matchManagers: [ + 'cargo', + ], + matchCurrentVersion: '>=1.0.0', + matchUpdateTypes: [ + 'minor', + ], + automerge: false, + groupName: 'compatible', + }, + ], +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/audit.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/audit.yml new file mode 100644 index 000000000..ea126fc60 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/audit.yml @@ -0,0 +1,30 @@ +name: Security audit + +permissions: + contents: read + +on: + pull_request: + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + push: + branches: + - master + +jobs: + cargo_deny: + runs-on: ubuntu-latest + strategy: + matrix: + checks: + - advisories + - bans licenses sources + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v2 + # Prevent sudden announcement of a new advisory from failing ci: + continue-on-error: ${{ matrix.checks == 'advisories' }} + with: + command: check ${{ matrix.checks }} + rust-version: stable diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/contrib.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/contrib.yml new file mode 100644 index 000000000..02dd4396a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/contrib.yml @@ -0,0 +1,52 @@ +name: Contrib Deploy +on: + push: + branches: + - master + +concurrency: + cancel-in-progress: false + group: "gh-pages" + +permissions: + contents: read + +jobs: + deploy: + permissions: + contents: write # for Git to git push + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install mdbook + run: | + mkdir mdbook + curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.44/mdbook-v0.4.44-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook + echo `pwd`/mdbook >> $GITHUB_PATH + - name: Deploy docs + run: | + GENERATE_PY="$(pwd)/ci/generate.py" + + cd src/doc/contrib + mdbook build + + # Override previous ref to avoid keeping history. + git worktree add --orphan -B gh-pages gh-pages + git config user.name "Deploy from CI" + git config user.email "" + cd gh-pages + mv ../book contrib + git add contrib + + # Generate HTML for link redirections. + python3 "$GENERATE_PY" + git add *.html + # WARN: The CNAME file is for GitHub to redirect requests to the custom domain. + # Missing this may entail security hazard and domain takeover. + # See + git add CNAME + + git commit -m "Deploy $GITHUB_SHA to gh-pages" + git push origin +gh-pages diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/main.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/main.yml new file mode 100644 index 000000000..19b920a2d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/main.yml @@ -0,0 +1,278 @@ +name: CI +on: + merge_group: + pull_request: + branches: + - "**" + +defaults: + run: + shell: bash + +permissions: + contents: read + +concurrency: + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + conclusion: + needs: + - build_std + - clippy + - msrv + - docs + - lint-docs + - lockfile + - resolver + - rustfmt + - test + - test_gitoxide + permissions: + contents: none + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' + + # Check Code style quickly by running `rustfmt` over all code + rustfmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update stable && rustup default stable + - run: rustup component add rustfmt + - run: cargo fmt --all --check + + # Ensure there are no clippy warnings + clippy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update stable && rustup default stable + - run: rustup component add clippy + - run: cargo clippy --workspace --all-targets --no-deps -- -D warnings + + stale-label: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - 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 + steps: + - uses: actions/checkout@v4 + - run: rustup update stable && rustup default stable + - run: cargo update -p cargo --locked + + check-version-bump: + runs-on: ubuntu-latest + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha != '' && github.event.pull_request.head.sha || github.sha }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - run: rustup update stable && rustup default stable + - name: Install cargo-semver-checks + run: | + mkdir installed-bins + curl -Lf https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.40.0/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz \ + | tar -xz --directory=./installed-bins + echo `pwd`/installed-bins >> $GITHUB_PATH + - run: ci/validate-version-bump.sh + + test: + runs-on: ${{ matrix.os }} + env: + CARGO_PROFILE_DEV_DEBUG: 1 + CARGO_PROFILE_TEST_DEBUG: 1 + CARGO_INCREMENTAL: 0 + CARGO_PUBLIC_NETWORK_TESTS: 1 + # Workaround for https://github.com/rust-lang/rustup/issues/3036 + RUSTUP_WINDOWS_PATH_ADD_BIN: 0 + strategy: + matrix: + include: + - name: Linux x86_64 stable + os: ubuntu-latest + rust: stable + other: i686-unknown-linux-gnu + - name: Linux x86_64 beta + os: ubuntu-latest + rust: beta + other: i686-unknown-linux-gnu + - name: Linux x86_64 nightly + os: ubuntu-latest + rust: nightly + other: i686-unknown-linux-gnu + - name: macOS aarch64 stable + os: macos-14 + rust: stable + other: x86_64-apple-darwin + - name: macOS x86_64 nightly + os: macos-13 + rust: nightly + other: x86_64-apple-ios + - name: macOS aarch64 nightly + os: macos-14 + rust: nightly + other: x86_64-apple-darwin + - name: Windows x86_64 MSVC stable + os: windows-latest + rust: stable-msvc + other: i686-pc-windows-msvc + - name: Windows x86_64 gnu nightly # runs out of space while trying to link the test suite + os: windows-latest + rust: nightly-gnu + other: i686-pc-windows-gnu + name: Tests ${{ matrix.name }} + steps: + - uses: actions/checkout@v4 + - name: Dump Environment + run: ci/dump-environment.sh + # Some tests require stable. Make sure it is set to the most recent stable + # so that we can predictably handle updates if necessary (and not randomly + # when GitHub updates its image). + - run: rustup update --no-self-update stable + - run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} + - run: rustup target add ${{ matrix.other }} + - run: rustup target add wasm32-unknown-unknown + - run: rustup target add aarch64-unknown-none # need this for build-std mock tests + if: startsWith(matrix.rust, 'nightly') + - run: rustup component add rustc-dev llvm-tools-preview rust-docs + if: startsWith(matrix.rust, 'nightly') + - run: sudo apt update -y && sudo apt install lldb gcc-multilib libsecret-1-0 libsecret-1-dev -y + if: matrix.os == 'ubuntu-latest' + - run: rustup component add rustfmt || echo "rustfmt not available" + - name: Configure extra test environment + run: echo CARGO_CONTAINER_TESTS=1 >> $GITHUB_ENV + if: matrix.os == 'ubuntu-latest' + - run: cargo test -p cargo + - name: Clear intermediate test output + run: ci/clean-test-output.sh + + - name: gitoxide tests (all git-related tests) + run: cargo test -p cargo git + env: + __CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2: 1 + # The testsuite generates a huge amount of data, and fetch-smoke-test was + # running out of disk space. + - name: Clear test output + run: ci/clean-test-output.sh + + # This only tests `cargo fix` because fix-proxy-mode is one of the most + # complicated subprocess management in Cargo. + - name: Check operability of rustc invocation with argfile + run: 'cargo test -p cargo --test testsuite -- fix::' + env: + __CARGO_TEST_FORCE_ARGFILE: 1 + - 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 + # download all workspaces. + cargo test -p benchsuite --all-targets -- cargo + cargo check -p capture + # The testsuite generates a huge amount of data, and fetch-smoke-test was + # running out of disk space. + - name: Clear benchmark output + run: ci/clean-test-output.sh + + - name: Fetch smoke test + run: ci/fetch-smoke-test.sh + + schema: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update stable && rustup default stable + - run: cargo test -p cargo-util-schemas -F unstable-schema + + resolver: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update stable && rustup default stable + - run: cargo test -p resolver-tests + + test_gitoxide: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update --no-self-update stable && rustup default stable + - run: rustup target add i686-unknown-linux-gnu + - run: rustup target add wasm32-unknown-unknown + - run: sudo apt update -y && sudo apt install gcc-multilib libsecret-1-0 libsecret-1-dev -y + - run: rustup component add rustfmt || echo "rustfmt not available" + - run: cargo test -p cargo + env: + __CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2: 1 + + build_std: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update nightly && rustup default nightly + - run: rustup component add rust-src + - run: cargo build + - run: cargo test -p cargo --test build-std + env: + CARGO_RUN_BUILD_STD_TESTS: 1 + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: rustup update nightly && rustup default nightly + - run: rustup update stable + - run: rustup component add rust-docs + - run: ci/validate-man.sh + # This requires rustfmt, use stable. + - name: Run semver-check + run: cargo +stable run -p semver-check + - name: Ensure intradoc links are valid + run: cargo doc --workspace --document-private-items --no-deps + env: + RUSTDOCFLAGS: -D warnings + - name: Install mdbook + run: | + mkdir mdbook + curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.44/mdbook-v0.4.44-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook + echo `pwd`/mdbook >> $GITHUB_PATH + - run: cd src/doc && mdbook build --dest-dir ../../target/doc + - name: Run linkchecker.sh + run: | + 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 + + msrv: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: taiki-e/install-action@cargo-hack + - run: cargo hack check --all-targets --rust-version --workspace --ignore-private --locked diff --git a/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/release.yml b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/release.yml new file mode 100644 index 000000000..0b31b6a63 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.github/workflows/release.yml @@ -0,0 +1,33 @@ +# Publish Cargo to crates.io whenever a new tag is pushed. Tags are pushed by +# the Rust release process (https://github.com/rust-lang/promote-release), +# which will cause this workflow to run. + +name: Release +on: + push: + tags: + - "0.*" + +# Prevent multiple releases from starting at the same time. +concurrency: + group: release + +jobs: + crates-io: + name: Publish on crates.io + runs-on: ubuntu-latest + permissions: + contents: read + + # Gain access to the crates.io publishing token. + environment: + name: release + + steps: + - name: Checkout the source code + uses: actions/checkout@v4 + + - name: Publish Cargo to crates.io + run: ./publish.py + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/collector/compile-benchmarks/cargo-0.87.1/.gitignore b/collector/compile-benchmarks/cargo-0.87.1/.gitignore new file mode 100644 index 000000000..e10c0128f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.gitignore @@ -0,0 +1,14 @@ +/target +/Cargo.lock +/config.stamp +/Makefile +/config.mk +/src/doc/build +/src/etc/*.pyc +/src/registry/target +rustc +__pycache__ +.idea/ +.vscode/ +*.iml +*.swp diff --git a/collector/compile-benchmarks/cargo-0.87.1/.ignore b/collector/compile-benchmarks/cargo-0.87.1/.ignore new file mode 100644 index 000000000..f10e171d3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/.ignore @@ -0,0 +1,15 @@ +# Output generated from src/doc/man +# +# The goal is to help people find the right file to edit +src/doc/man/generated_txt +src/doc/src/commands/* +src/etc/man +!src/doc/src/commands/build-commands.md +!src/doc/src/commands/cargo-clippy.md +!src/doc/src/commands/cargo-fmt.md +!src/doc/src/commands/cargo-miri.md +!src/doc/src/commands/general-commands.md +!src/doc/src/commands/index.md +!src/doc/src/commands/manifest-commands.md +!src/doc/src/commands/package-commands.md +!src/doc/src/commands/publishg-commands.md diff --git a/collector/compile-benchmarks/cargo-0.87.1/CHANGELOG.md b/collector/compile-benchmarks/cargo-0.87.1/CHANGELOG.md new file mode 100644 index 000000000..9228e04c7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +The changelog has moved to the [Cargo Book](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html). diff --git a/collector/compile-benchmarks/cargo-0.87.1/CODE_OF_CONDUCT.md b/collector/compile-benchmarks/cargo-0.87.1/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..e3708bc48 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# The Rust Code of Conduct + +The Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html). diff --git a/collector/compile-benchmarks/cargo-0.87.1/CONTRIBUTING.md b/collector/compile-benchmarks/cargo-0.87.1/CONTRIBUTING.md new file mode 100644 index 000000000..6046d5a35 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/CONTRIBUTING.md @@ -0,0 +1,19 @@ +# Contributing to Cargo + +Contributing documentation has moved to the **[Cargo Contributor Guide]**. + +[Cargo Contributor Guide]: https://rust-lang.github.io/cargo/contrib/ + +## Before hacking on Cargo + +We encourage people to discuss their design before hacking on code. Typically, +you [file an issue] or start a thread on the [internals forum] before submitting +a pull request. + +Please read [the process] of how features and bugs are managed in Cargo. +**Only issues that have been explicitly marked as [accepted] will be reviewed.** + +[internals forum]: https://internals.rust-lang.org/c/tools-and-infrastructure/cargo +[file an issue]: https://github.com/rust-lang/cargo/issues +[the process]: https://doc.crates.io/contrib/process/index.html +[accepted]: https://github.com/rust-lang/cargo/issues?q=is%3Aissue+is%3Aopen+label%3AS-accepted diff --git a/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml b/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml new file mode 100644 index 000000000..65a7b97a0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml @@ -0,0 +1,395 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.84" +name = "cargo" +version = "0.87.1" +build = "build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = """ +Cargo, a package manager for Rust. +""" +homepage = "https://doc.rust-lang.org/cargo/index.html" +documentation = "https://docs.rs/cargo" +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/cargo" + +[features] +all-static = [ + "vendored-openssl", + "curl/static-curl", + "curl/force-system-lib-on-osx", + "vendored-libgit2", +] +vendored-libgit2 = ["libgit2-sys/vendored"] +vendored-openssl = ["openssl/vendored"] + +[lib] +name = "cargo" +path = "src/cargo/lib.rs" + +[[bin]] +name = "cargo" +path = "src/bin/cargo/main.rs" +test = false +doc = false + +[[test]] +name = "build-std" +path = "tests/build-std/main.rs" + +[[test]] +name = "testsuite" +path = "tests/testsuite/main.rs" + +[dependencies.annotate-snippets] +version = "0.11.5" + +[dependencies.anstream] +version = "0.6.18" + +[dependencies.anstyle] +version = "1.0.10" + +[dependencies.anyhow] +version = "1.0.95" + +[dependencies.base64] +version = "0.22.1" + +[dependencies.blake3] +version = "1.5.5" + +[dependencies.bytesize] +version = "1.3" + +[dependencies.cargo-credential] +version = "0.4.2" + +[dependencies.cargo-platform] +version = "0.2.0" + +[dependencies.cargo-util] +version = "0.2.19" + +[dependencies.cargo-util-schemas] +version = "0.8.0" + +[dependencies.clap] +version = "4.5.28" +features = ["wrap_help"] + +[dependencies.clap_complete] +version = "4.5.44" +features = ["unstable-dynamic"] + +[dependencies.color-print] +version = "0.3.7" + +[dependencies.crates-io] +version = "0.40.9" + +[dependencies.curl] +version = "0.4.47" +features = ["http2"] + +[dependencies.curl-sys] +version = "0.4.79" + +[dependencies.filetime] +version = "0.2.25" + +[dependencies.flate2] +version = "1.0.35" +features = ["zlib"] +default-features = false + +[dependencies.git2] +version = "0.20.0" + +[dependencies.git2-curl] +version = "0.21.0" + +[dependencies.gix] +version = "0.70.0" +features = [ + "blocking-http-transport-curl", + "progress-tree", + "parallel", + "dirwalk", +] +default-features = false + +[dependencies.glob] +version = "0.3.2" + +[dependencies.hex] +version = "0.4.3" + +[dependencies.hmac] +version = "0.12.1" + +[dependencies.home] +version = "0.5.11" + +[dependencies.http-auth] +version = "0.1.10" +default-features = false + +[dependencies.humantime] +version = "2.1.0" + +[dependencies.ignore] +version = "0.4.23" + +[dependencies.im-rc] +version = "15.1.0" + +[dependencies.indexmap] +version = "2.7.1" + +[dependencies.itertools] +version = "0.14.0" + +[dependencies.jobserver] +version = "0.1.32" + +[dependencies.lazycell] +version = "1.3.0" + +[dependencies.libgit2-sys] +version = "0.18.0" + +[dependencies.memchr] +version = "2.7.4" + +[dependencies.opener] +version = "0.7.2" + +[dependencies.os_info] +version = "3.10.0" +default-features = false + +[dependencies.pasetors] +version = "0.7.2" +features = [ + "v3", + "paserk", + "std", + "serde", +] + +[dependencies.pathdiff] +version = "0.2.3" + +[dependencies.rand] +version = "0.9.0" + +[dependencies.regex] +version = "1.11.1" + +[dependencies.rusqlite] +version = "0.33.0" +features = ["bundled"] + +[dependencies.rustc-hash] +version = "2.1.1" + +[dependencies.rustc-stable-hash] +version = "0.1.1" + +[dependencies.rustfix] +version = "0.9.0" + +[dependencies.same-file] +version = "1.0.6" + +[dependencies.semver] +version = "1.0.25" +features = ["serde"] + +[dependencies.serde] +version = "1.0.217" +features = ["derive"] + +[dependencies.serde-untagged] +version = "0.1.6" + +[dependencies.serde_ignored] +version = "0.1.10" + +[dependencies.serde_json] +version = "1.0.138" +features = ["raw_value"] + +[dependencies.sha1] +version = "0.10.6" + +[dependencies.shell-escape] +version = "0.1.5" + +[dependencies.supports-hyperlinks] +version = "3.1.0" + +[dependencies.supports-unicode] +version = "3.0.0" + +[dependencies.tar] +version = "0.4.43" +default-features = false + +[dependencies.tempfile] +version = "3.16.0" + +[dependencies.thiserror] +version = "2.0.11" + +[dependencies.time] +version = "0.3.37" +features = [ + "parsing", + "formatting", + "serde", +] + +[dependencies.toml] +version = "0.8.20" + +[dependencies.toml_edit] +version = "0.22.23" +features = ["serde"] + +[dependencies.tracing] +version = "0.1.41" +features = [ + "std", + "attributes", +] +default-features = false + +[dependencies.tracing-subscriber] +version = "0.3.19" +features = ["env-filter"] + +[dependencies.unicase] +version = "2.8.1" + +[dependencies.unicode-width] +version = "0.2.0" + +[dependencies.url] +version = "2.5.4" + +[dependencies.walkdir] +version = "2.5.0" + +[dev-dependencies.annotate-snippets] +version = "0.11.5" +features = ["testing-colors"] + +[dev-dependencies.cargo-test-support] +version = "0.7.1" + +[dev-dependencies.gix] +version = "0.70.0" +features = [ + "blocking-http-transport-curl", + "progress-tree", + "parallel", + "dirwalk", + "revision", +] +default-features = false + +[dev-dependencies.same-file] +version = "1.0.6" + +[dev-dependencies.snapbox] +version = "0.6.21" +features = [ + "diff", + "dir", + "term-svg", + "regex", + "json", +] + +[build-dependencies.flate2] +version = "1.0.35" +features = ["zlib"] +default-features = false + +[build-dependencies.tar] +version = "0.4.43" +default-features = false + +[target."cfg(not(windows))".dependencies.openssl] +version = "=0.10.57" +optional = true + +[target."cfg(not(windows))".dependencies.openssl-sys] +version = "=0.9.92" +optional = true + +[target.'cfg(target_has_atomic = "64")'.dependencies.tracing-chrome] +version = "0.7.2" + +[target.'cfg(target_os = "linux")'.dependencies.cargo-credential-libsecret] +version = "0.4.12" + +[target.'cfg(target_os = "macos")'.dependencies.cargo-credential-macos-keychain] +version = "0.4.12" + +[target."cfg(unix)".dependencies.libc] +version = "0.2.169" + +[target."cfg(windows)".dependencies.cargo-credential-wincred] +version = "0.4.12" + +[target."cfg(windows)".dependencies.windows-sys] +version = "0.59" +features = [ + "Win32_Foundation", + "Win32_Security", + "Win32_Storage_FileSystem", + "Win32_System_IO", + "Win32_System_Console", + "Win32_System_JobObjects", + "Win32_System_Threading", +] + +[lints.clippy] +dbg_macro = "warn" +disallowed_methods = "warn" +print_stderr = "warn" +print_stdout = "warn" +self_named_module_files = "warn" + +[lints.clippy.all] +level = "allow" +priority = -2 + +[lints.clippy.correctness] +level = "warn" +priority = -1 + +[lints.rust] +rust_2018_idioms = "warn" + +[lints.rustdoc] +private_intra_doc_links = "allow" diff --git a/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml.orig b/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml.orig new file mode 100644 index 000000000..54447b671 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml.orig @@ -0,0 +1,277 @@ +[workspace] +resolver = "2" +members = [ + "crates/*", + "credential/*", + "benches/benchsuite", + "benches/capture", +] +exclude = [ + "target/", # exclude bench testing +] + +[workspace.package] +rust-version = "1.82" # MSRV:3 +edition = "2021" +license = "MIT OR Apache-2.0" +homepage = "https://github.com/rust-lang/cargo" +repository = "https://github.com/rust-lang/cargo" + +[workspace.dependencies] +annotate-snippets = "0.11.5" +anstream = "0.6.18" +anstyle = "1.0.10" +anyhow = "1.0.95" +base64 = "0.22.1" +blake3 = "1.5.5" +build-rs = { version = "0.3.0", path = "crates/build-rs" } +bytesize = "1.3" +cargo = { path = "" } +cargo-credential = { version = "0.4.2", path = "credential/cargo-credential" } +cargo-credential-libsecret = { version = "0.4.12", path = "credential/cargo-credential-libsecret" } +cargo-credential-macos-keychain = { version = "0.4.12", path = "credential/cargo-credential-macos-keychain" } +cargo-credential-wincred = { version = "0.4.12", path = "credential/cargo-credential-wincred" } +cargo-platform = { path = "crates/cargo-platform", version = "0.2.0" } +cargo-test-macro = { version = "0.4.1", path = "crates/cargo-test-macro" } +cargo-test-support = { version = "0.7.1", path = "crates/cargo-test-support" } +cargo-util = { version = "0.2.19", path = "crates/cargo-util" } +cargo-util-schemas = { version = "0.8.0", path = "crates/cargo-util-schemas" } +cargo_metadata = "0.19.1" +clap = "4.5.28" +clap_complete = { version = "4.5.44", features = ["unstable-dynamic"] } +color-print = "0.3.7" +core-foundation = { version = "0.10.0", features = ["mac_os_10_7_support"] } +crates-io = { version = "0.40.9", path = "crates/crates-io" } +criterion = { version = "0.5.1", features = ["html_reports"] } +curl = "0.4.47" +curl-sys = "0.4.79" +filetime = "0.2.25" +flate2 = { version = "1.0.35", default-features = false, features = ["zlib"] } +git2 = "0.20.0" +git2-curl = "0.21.0" +gix = { version = "0.70.0", default-features = false, features = ["blocking-http-transport-curl", "progress-tree", "parallel", "dirwalk"] } +glob = "0.3.2" +handlebars = { version = "6.3.1", features = ["dir_source"] } +hex = "0.4.3" +hmac = "0.12.1" +home = "0.5.11" +http-auth = { version = "0.1.10", default-features = false } +humantime = "2.1.0" +ignore = "0.4.23" +im-rc = "15.1.0" +indexmap = "2.7.1" +itertools = "0.14.0" +jobserver = "0.1.32" +lazycell = "1.3.0" +libc = "0.2.169" +libgit2-sys = "0.18.0" +libloading = "0.8.6" +memchr = "2.7.4" +miow = "0.6.0" +opener = "0.7.2" +openssl = "=0.10.57" # See rust-lang/cargo#13546 and openssl/openssl#23376 for pinning +openssl-sys = "=0.9.92" # See rust-lang/cargo#13546 and openssl/openssl#23376 for pinning +os_info = { version = "3.10.0", default-features = false } +pasetors = { version = "0.7.2", features = ["v3", "paserk", "std", "serde"] } +pathdiff = "0.2.3" +percent-encoding = "2.3.1" +pkg-config = "0.3.31" +proptest = "1.6.0" +pulldown-cmark = { version = "0.12.2", default-features = false, features = ["html"] } +rand = "0.9.0" +regex = "1.11.1" +rusqlite = { version = "0.33.0", features = ["bundled"] } +rustc-hash = "2.1.1" +rustc-stable-hash = "0.1.1" +rustfix = { version = "0.9.0", path = "crates/rustfix" } +same-file = "1.0.6" +schemars = "1.0.0-alpha.17" +security-framework = "3.2.0" +semver = { version = "1.0.25", features = ["serde"] } +serde = "1.0.217" +serde-untagged = "0.1.6" +serde-value = "0.7.0" +serde_ignored = "0.1.10" +serde_json = "1.0.138" +sha1 = "0.10.6" +sha2 = "0.10.8" +shell-escape = "0.1.5" +similar = "2.7.0" +supports-hyperlinks = "3.1.0" +supports-unicode = "3.0.0" +snapbox = { version = "0.6.21", features = ["diff", "dir", "term-svg", "regex", "json"] } +tar = { version = "0.4.43", default-features = false } +tempfile = "3.16.0" +thiserror = "2.0.11" +time = { version = "0.3.37", features = ["parsing", "formatting", "serde"] } +toml = "0.8.20" +toml_edit = { version = "0.22.23", features = ["serde"] } +tracing = { version = "0.1.41", default-features = false, features = ["std"] } # be compatible with rustc_log: https://github.com/rust-lang/rust/blob/e51e98dde6a/compiler/rustc_log/Cargo.toml#L9 +tracing-chrome = "0.7.2" +tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } +unicase = "2.8.1" +unicode-ident = "1.0.16" +unicode-width = "0.2.0" +unicode-xid = "0.2.6" +url = "2.5.4" +varisat = "0.2.2" +walkdir = "2.5.0" +windows-sys = "0.59" + +[workspace.lints.rust] +rust_2018_idioms = "warn" # TODO: could this be removed? + +[workspace.lints.rustdoc] +private_intra_doc_links = "allow" + +[workspace.lints.clippy] +all = { level = "allow", priority = -2 } +correctness = { level = "warn", priority = -1 } +dbg_macro = "warn" +disallowed_methods = "warn" +print_stderr = "warn" +print_stdout = "warn" +self_named_module_files = "warn" + +[package] +name = "cargo" +version = "0.87.1" +edition.workspace = true +license.workspace = true +rust-version = "1.84" # MSRV:1 +homepage = "https://doc.rust-lang.org/cargo/index.html" +repository.workspace = true +documentation = "https://docs.rs/cargo" +description = """ +Cargo, a package manager for Rust. +""" + +[lib] +name = "cargo" +path = "src/cargo/lib.rs" + +[dependencies] +annotate-snippets.workspace = true +anstream.workspace = true +anstyle.workspace = true +anyhow.workspace = true +base64.workspace = true +blake3.workspace = true +bytesize.workspace = true +cargo-credential.workspace = true +cargo-platform.workspace = true +cargo-util-schemas.workspace = true +cargo-util.workspace = true +clap = { workspace = true, features = ["wrap_help"] } +clap_complete.workspace = true +color-print.workspace = true +crates-io.workspace = true +curl = { workspace = true, features = ["http2"] } +curl-sys.workspace = true +filetime.workspace = true +flate2.workspace = true +git2.workspace = true +git2-curl.workspace = true +gix.workspace = true +glob.workspace = true +hex.workspace = true +hmac.workspace = true +home.workspace = true +http-auth.workspace = true +humantime.workspace = true +ignore.workspace = true +im-rc.workspace = true +indexmap.workspace = true +itertools.workspace = true +jobserver.workspace = true +lazycell.workspace = true +libgit2-sys.workspace = true +memchr.workspace = true +opener.workspace = true +os_info.workspace = true +pasetors.workspace = true +pathdiff.workspace = true +rand.workspace = true +regex.workspace = true +rusqlite.workspace = true +rustc-hash.workspace = true +rustc-stable-hash.workspace = true +rustfix.workspace = true +same-file.workspace = true +semver.workspace = true +serde = { workspace = true, features = ["derive"] } +serde-untagged.workspace = true +serde_ignored.workspace = true +serde_json = { workspace = true, features = ["raw_value"] } +sha1.workspace = true +shell-escape.workspace = true +supports-hyperlinks.workspace = true +supports-unicode.workspace = true +tar.workspace = true +tempfile.workspace = true +thiserror.workspace = true +time.workspace = true +toml.workspace = true +toml_edit.workspace = true +tracing = { workspace = true, features = ["attributes"] } +tracing-subscriber.workspace = true +unicase.workspace = true +unicode-width.workspace = true +url.workspace = true +walkdir.workspace = true + +[target.'cfg(target_has_atomic = "64")'.dependencies] +tracing-chrome.workspace = true + +[target.'cfg(unix)'.dependencies] +libc.workspace = true + +[target.'cfg(target_os = "linux")'.dependencies] +cargo-credential-libsecret.workspace = true + +[target.'cfg(target_os = "macos")'.dependencies] +cargo-credential-macos-keychain.workspace = true + +[target.'cfg(not(windows))'.dependencies] +openssl = { workspace = true, optional = true } +openssl-sys = { workspace = true, optional = true } # HACK: for pinning to openssl v1. + +[target.'cfg(windows)'.dependencies] +cargo-credential-wincred.workspace = true + +[target.'cfg(windows)'.dependencies.windows-sys] +workspace = true +features = [ + "Win32_Foundation", + "Win32_Security", + "Win32_Storage_FileSystem", + "Win32_System_IO", + "Win32_System_Console", + "Win32_System_JobObjects", + "Win32_System_Threading", +] + +[dev-dependencies] +annotate-snippets = { workspace = true, features = ["testing-colors"] } +cargo-test-support.workspace = true +gix = { workspace = true, features = ["revision"] } +same-file.workspace = true +snapbox.workspace = true + +[build-dependencies] +flate2.workspace = true +tar.workspace = true + +[[bin]] +name = "cargo" +test = false +doc = false + +[features] +vendored-openssl = ["openssl/vendored"] +vendored-libgit2 = ["libgit2-sys/vendored"] +# This is primarily used by rust-lang/rust distributing cargo the executable. +all-static = ['vendored-openssl', 'curl/static-curl', 'curl/force-system-lib-on-osx', 'vendored-libgit2'] + +[lints] +workspace = true diff --git a/collector/compile-benchmarks/cargo-0.87.1/LICENSE-APACHE b/collector/compile-benchmarks/cargo-0.87.1/LICENSE-APACHE new file mode 100644 index 000000000..c98d27d4f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/LICENSE-2.0 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/collector/compile-benchmarks/cargo-0.87.1/LICENSE-MIT b/collector/compile-benchmarks/cargo-0.87.1/LICENSE-MIT new file mode 100644 index 000000000..31aa79387 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/collector/compile-benchmarks/cargo-0.87.1/LICENSE-THIRD-PARTY b/collector/compile-benchmarks/cargo-0.87.1/LICENSE-THIRD-PARTY new file mode 100644 index 000000000..8f83ab502 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/LICENSE-THIRD-PARTY @@ -0,0 +1,1272 @@ +The Cargo source code itself does not bundle any third party libraries, but it +depends on a number of libraries which carry their own copyright notices and +license terms. These libraries are normally all linked static into the binary +distributions of Cargo: + +* OpenSSL - https://www.openssl.org/source/license.html + + Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. All advertising materials mentioning features or use of this + software must display the following acknowledgment: + "This product includes software developed by the OpenSSL Project + for use in the OpenSSL Toolkit. (https://www.openssl.org/)" + + 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + endorse or promote products derived from this software without + prior written permission. For written permission, please contact + openssl-core@openssl.org. + + 5. Products derived from this software may not be called "OpenSSL" + nor may "OpenSSL" appear in their names without prior written + permission of the OpenSSL Project. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes software developed by the OpenSSL Project + for use in the OpenSSL Toolkit (https://www.openssl.org/)" + + THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + ==================================================================== + + This product includes cryptographic software written by Eric Young + (eay@cryptsoft.com). This product includes software written by Tim + Hudson (tjh@cryptsoft.com). + + --- + + Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + All rights reserved. + + This package is an SSL implementation written + by Eric Young (eay@cryptsoft.com). + The implementation was written so as to conform with Netscapes SSL. + + This library is free for commercial and non-commercial use as long as + the following conditions are aheared to. The following conditions + apply to all code found in this distribution, be it the RC4, RSA, + lhash, DES, etc., code; not just the SSL code. The SSL documentation + included with this distribution is covered by the same copyright terms + except that the holder is Tim Hudson (tjh@cryptsoft.com). + + Copyright remains Eric Young's, and as such any Copyright notices in + the code are not to be removed. + If this package is used in a product, Eric Young should be given attribution + as the author of the parts of the library used. + This can be in the form of a textual message at program startup or + in documentation (online or textual) provided with the package. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + "This product includes cryptographic software written by + Eric Young (eay@cryptsoft.com)" + The word 'cryptographic' can be left out if the rouines from the library + being used are not cryptographic related :-). + 4. If you include any Windows specific code (or a derivative thereof) from + the apps directory (application code) you must include an acknowledgement: + "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + + THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + The licence and distribution terms for any publically available version or + derivative of this code cannot be changed. i.e. this code cannot simply be + copied and put under another distribution licence + [including the GNU Public Licence.] + +* libgit2 - https://github.com/libgit2/libgit2/blob/master/COPYING + + libgit2 is Copyright (C) the libgit2 contributors, + unless otherwise stated. See the AUTHORS file for details. + + Note that the only valid version of the GPL as far as this project + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + ---------------------------------------------------------------------- + + LINKING EXCEPTION + + In addition to the permissions in the GNU General Public License, + the authors give you unlimited permission to link the compiled + version of this library into combinations with other programs, + and to distribute those combinations without any restriction + coming from the use of this file. (The General Public License + restrictions do apply in other respects; for example, they cover + modification of the file, and distribution when not linked into + a combined executable.) + + ---------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + License is intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Library General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains + a notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the + Program (independent of having been made by running the Program). + Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and give any other recipients of the Program a copy of this License + along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this License. + However, parties who have received copies, or rights, from you under + this License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions + of the General Public License from time to time. Such new versions will + be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and conditions + either of that version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number of + this License, you may choose any version ever published by the Free Software + Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the author + to ask for permission. For software which is copyrighted by the Free + Software Foundation, write to the Free Software Foundation; we sometimes + make exceptions for this. Our decision will be guided by the two goals + of preserving the free status of all derivatives of our free software and + of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS + TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, + INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING + OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED + TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY + YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the appropriate + parts of the General Public License. Of course, the commands you use may + be called something other than `show w' and `show c'; they could even be + mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Library General + Public License instead of this License. + + ---------------------------------------------------------------------- + + The bundled ZLib code is licensed under the ZLib license: + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + ---------------------------------------------------------------------- + + The Clar framework is licensed under the MIT license: + + Copyright (C) 2011 by Vicent Marti + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + ---------------------------------------------------------------------- + + The regex library (deps/regex/) is licensed under the GNU LGPL + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + [This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + Licenses are intended to guarantee your freedom to share and change + free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some + specially designated software packages--typically libraries--of the + Free Software Foundation and other authors who decide to use it. You + can use it too, but we suggest you first think carefully about whether + this license or the ordinary General Public License is the better + strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, + not price. Our General Public Licenses are designed to make sure that + you have the freedom to distribute copies of free software (and charge + for this service if you wish); that you receive source code or can get + it if you want it; that you can change the software and use pieces of + it in new free programs; and that you are informed that you can do + these things. + + To protect your rights, we need to make restrictions that forbid + distributors to deny you these rights or to ask you to surrender these + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis + or for a fee, you must give the recipients all the rights that we gave + you. You must make sure that they, too, receive or can get the source + code. If you link other code with the library, you must provide + complete object files to the recipients, so that they can relink them + with the library after making changes to the library and recompiling + it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the + library, and (2) we offer you this license, which gives you legal + permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that + there is no warranty for the free library. Also, if the library is + modified by someone else and passed on, the recipients should know + that what they have is not the original version, so that the original + author's reputation will not be affected by problems that might be + introduced by others. + + Finally, software patents pose a constant threat to the existence of + any free program. We wish to make sure that a company cannot + effectively restrict the users of a free program by obtaining a + restrictive license from a patent holder. Therefore, we insist that + any patent license obtained for a version of the library must be + consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the + ordinary GNU General Public License. This license, the GNU Lesser + General Public License, applies to certain designated libraries, and + is quite different from the ordinary General Public License. We use + this license for certain libraries in order to permit linking those + libraries into non-free programs. + + When a program is linked with a library, whether statically or using + a shared library, the combination of the two is legally speaking a + combined work, a derivative of the original library. The ordinary + General Public License therefore permits such linking only if the + entire combination fits its criteria of freedom. The Lesser General + Public License permits more lax criteria for linking other code with + the library. + + We call this license the "Lesser" General Public License because it + does Less to protect the user's freedom than the ordinary General + Public License. It also provides other free software developers Less + of an advantage over competing non-free programs. These disadvantages + are the reason we use the ordinary General Public License for many + libraries. However, the Lesser license provides advantages in certain + special circumstances. + + For example, on rare occasions, there may be a special need to + encourage the widest possible use of a certain library, so that it becomes + a de-facto standard. To achieve this, non-free programs must be + allowed to use the library. A more frequent case is that a free + library does the same job as widely used non-free libraries. In this + case, there is little to gain by limiting the free library to free + software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free + programs enables a greater number of people to use a large body of + free software. For example, permission to use the GNU C Library in + non-free programs enables many more people to use the whole GNU + operating system, as well as its variant, the GNU/Linux operating + system. + + Although the Lesser General Public License is Less protective of the + users' freedom, it does ensure that the user of a program that is + linked with the Library has the freedom and the wherewithal to run + that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, whereas the latter must + be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other + program which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under the terms of + this Lesser General Public License (also called "this License"). + Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or translated + straightforwardly into another language. (Hereinafter, translation is + included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for + making modifications to it. For a library, complete source code means + all the source code for all modules it contains, plus any associated + interface definition files, plus the scripts used to control compilation + and installation of the library. + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running a program using the Library is not restricted, and output from + such a program is covered only if its contents constitute a work based + on the Library (independent of the use of the Library in a tool for + writing it). Whether that is true depends on what the Library does + and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's + complete source code as you receive it, in any medium, provided that + you conspicuously and appropriately publish on each copy an + appropriate copyright notice and disclaimer of warranty; keep intact + all the notices that refer to this License and to the absence of any + warranty; and distribute a copy of this License along with the + Library. + + You may charge a fee for the physical act of transferring a copy, + and you may at your option offer warranty protection in exchange for a + fee. + + 2. You may modify your copy or copies of the Library or any portion + of it, thus forming a work based on the Library, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Library, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Library, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote + it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Library. + + In addition, mere aggregation of another work not based on the Library + with the Library (or with a work based on the Library) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public + License instead of this License to a given copy of the Library. To do + this, you must alter all the notices that refer to this License, so + that they refer to the ordinary GNU General Public License, version 2, + instead of to this License. (If a newer version than version 2 of the + ordinary GNU General Public License has appeared, then you can specify + that version instead if you wish.) Do not make any other change in + these notices. + + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to all + subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of + the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or + derivative of it, under Section 2) in object code or executable form + under the terms of Sections 1 and 2 above provided that you accompany + it with the complete corresponding machine-readable source code, which + must be distributed under the terms of Sections 1 and 2 above on a + medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy the + source code from the same place satisfies the requirement to + distribute the source code, even though third parties are not + compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being compiled or + linked with it, is called a "work that uses the Library". Such a + work, in isolation, is not a derivative work of the Library, and + therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file + that is part of the Library, the object code for the work may be a + derivative work of the Library even though the source code is not. + Whether this is true is especially significant if the work can be + linked without the Library, or if the work is itself a library. The + threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the object + file is unrestricted, regardless of whether it is legally a derivative + work. (Executables containing this object code plus portions of the + Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section 6. + Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or + link a "work that uses the Library" with the Library to produce a + work containing portions of the Library, and distribute that work + under terms of your choice, provided that the terms permit + modification of the work for the customer's own use and reverse + engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the + Library is used in it and that the Library and its use are covered by + this License. You must supply a copy of this License. If the work + during execution displays copyright notices, you must include the + copyright notice for the Library among them, as well as a reference + directing the user to the copy of this License. Also, you must do one + of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the + Library" must include any data and utility programs needed for + reproducing the executable from it. However, as a special exception, + the materials to be distributed need not include anything that is + normally distributed (in either source or binary form) with the major + components (compiler, kernel, and so on) of the operating system on + which the executable runs, unless that component itself accompanies + the executable. + + It may happen that this requirement contradicts the license + restrictions of other proprietary libraries that do not normally + accompany the operating system. Such a contradiction means you cannot + use both them and the Library together in an executable that you + distribute. + + 7. You may place library facilities that are a work based on the + Library side-by-side in a single library together with other library + facilities not covered by this License, and distribute such a combined + library, provided that the separate distribution of the work based on + the Library and of the other library facilities is otherwise + permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute + the Library except as expressly provided under this License. Any + attempt otherwise to copy, modify, sublicense, link with, or + distribute the Library is void, and will automatically terminate your + rights under this License. However, parties who have received copies, + or rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Library or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Library (or any work based on the + Library), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the + Library), the recipient automatically receives a license from the + original licensor to copy, distribute, link with or modify the Library + subject to these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties with + this License. + + 11. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Library at all. For example, if a patent + license would not permit royalty-free redistribution of the Library by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Library. + + If any portion of this section is held invalid or unenforceable under any + particular circumstance, the balance of the section is intended to apply, + and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Library under this License may add + an explicit geographical distribution limitation excluding those countries, + so that distribution is permitted only in or among countries not thus + excluded. In such case, this License incorporates the limitation as if + written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new + versions of the Lesser General Public License from time to time. + Such new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Library + specifies a version number of this License which applies to it and + "any later version", you have the option of following the terms and + conditions either of that version or of any later version published by + the Free Software Foundation. If the Library does not specify a + license version number, you may choose any version ever published by + the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free + programs whose distribution conditions are incompatible with these, + write to the author to ask for permission. For software which is + copyrighted by the Free Software Foundation, write to the Free + Software Foundation; we sometimes make exceptions for this. Our + decision will be guided by the two goals of preserving the free status + of all derivatives of our free software and of promoting the sharing + and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. + EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE + LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME + THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN + WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY + AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU + FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE + LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING + RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A + FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF + SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest + possible use to the public, we recommend making it free software that + everyone can redistribute and change. You can do so by permitting + redistribution under these terms (or, alternatively, under the terms of the + ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is + safest to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least the + "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + Also add information on how to contact you by electronic and paper mail. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the library, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + + That's all there is to it! + + ---------------------------------------------------------------------- + +* libssh2 - https://www.libssh2.org/license.html + + Copyright (c) 2004-2007 Sara Golemon + Copyright (c) 2005,2006 Mikhail Gusarov + Copyright (c) 2006-2007 The Written Word, Inc. + Copyright (c) 2007 Eli Fant + Copyright (c) 2009 Daniel Stenberg + Copyright (C) 2008, 2009 Simon Josefsson + All rights reserved. + + Redistribution and use in source and binary forms, + with or without modification, are permitted provided + that the following conditions are met: + + Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + Neither the name of the copyright holder nor the names + of any other contributors may be used to endorse or + promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + OF SUCH DAMAGE. + +* libcurl - https://curl.haxx.se/docs/copyright.html + + COPYRIGHT AND PERMISSION NOTICE + + Copyright (c) 1996 - 2014, Daniel Stenberg, daniel@haxx.se. + + All rights reserved. + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of a copyright holder shall not + be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization of the + copyright holder. + +* flate2-rs - https://github.com/alexcrichton/flate2-rs/blob/master/LICENSE-MIT +* link-config - https://github.com/alexcrichton/link-config/blob/master/LICENSE-MIT +* openssl-static-sys - https://github.com/alexcrichton/openssl-static-sys/blob/master/LICENSE-MIT +* toml-rs - https://github.com/alexcrichton/toml-rs/blob/master/LICENSE-MIT +* libssh2-static-sys - https://github.com/alexcrichton/libssh2-static-sys/blob/master/LICENSE-MIT +* git2-rs - https://github.com/alexcrichton/git2-rs/blob/master/LICENSE-MIT +* tar-rs - https://github.com/alexcrichton/tar-rs/blob/master/LICENSE-MIT + + Copyright (c) 2014 Alex Crichton + + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice + shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +* glob - https://github.com/rust-lang/glob/blob/master/LICENSE-MIT +* semver - https://github.com/rust-lang/semver/blob/master/LICENSE-MIT + + Copyright (c) 2014 The Rust Project Developers + + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice + shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +* rust-url - https://github.com/servo/rust-url/blob/master/LICENSE-MIT + + Copyright (c) 2006-2009 Graydon Hoare + Copyright (c) 2009-2013 Mozilla Foundation + + Permission is hereby granted, free of charge, to any + person obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without + limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of + the Software, and to permit persons to whom the Software + is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice + shall be included in all copies or substantial portions + of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +* rust-encoding - https://github.com/lifthrasiir/rust-encoding/blob/master/LICENSE.txt + + The MIT License (MIT) + + Copyright (c) 2013, Kang Seonghoon. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +* curl-rust - https://github.com/carllerche/curl-rust/blob/master/LICENSE + + Copyright (c) 2014 Carl Lerche + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +* docopt.rs - https://github.com/docopt/docopt.rs/blob/master/UNLICENSE + + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + For more information, please refer to + diff --git a/collector/compile-benchmarks/cargo-0.87.1/README.md b/collector/compile-benchmarks/cargo-0.87.1/README.md new file mode 100644 index 000000000..9d4bc9773 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/README.md @@ -0,0 +1,129 @@ +# Cargo + +Cargo downloads your Rust project’s dependencies and compiles your project. + +**To start using Cargo**, learn more at [The Cargo Book]. + +**To start developing Cargo itself**, read the [Cargo Contributor Guide]. + +[The Cargo Book]: https://doc.rust-lang.org/cargo/ +[Cargo Contributor Guide]: https://rust-lang.github.io/cargo/contrib/ + +> The Cargo binary distributed through with Rust is maintained by the Cargo +> team for use by the wider ecosystem. +> For all other uses of this crate (as a binary or library) this is maintained +> by the Cargo team, primarily for use by Cargo and not intended for external +> use (except as a transitive dependency). This crate may make major changes to +> its APIs. + +## Code Status + +[![CI](https://github.com/rust-lang/cargo/actions/workflows/main.yml/badge.svg?branch=auto-cargo)](https://github.com/rust-lang/cargo/actions/workflows/main.yml) + +Code documentation: + +## Compiling from Source + +### Requirements + +Cargo requires the following tools and packages to build: + +* `cargo` and `rustc` +* A C compiler [for your platform](https://github.com/rust-lang/cc-rs#compile-time-requirements) +* `git` (to clone this repository) + +**Other requirements:** + +The following are optional based on your platform and needs. + +* `pkg-config` — This is used to help locate system packages, such as `libssl` headers/libraries. This may not be required in all cases, such as using vendored OpenSSL, or on Windows. +* OpenSSL — Only needed on Unix-like systems and only if the `vendored-openssl` Cargo feature is not used. + + This requires the development headers, which can be obtained from the `libssl-dev` package on Ubuntu or `openssl-devel` with apk or yum or the `openssl` package from Homebrew on macOS. + + If using the `vendored-openssl` Cargo feature, then a static copy of OpenSSL will be built from source instead of using the system OpenSSL. + This may require additional tools such as `perl` and `make`. + + On macOS, common installation directories from Homebrew, MacPorts, or pkgsrc will be checked. Otherwise it will fall back to `pkg-config`. + + On Windows, the system-provided Schannel will be used instead. + + LibreSSL is also supported. + +**Optional system libraries:** + +The build will automatically use vendored versions of the following libraries. However, if they are provided by the system and can be found with `pkg-config`, then the system libraries will be used instead: + +* [`libcurl`](https://curl.se/libcurl/) — Used for network transfers. +* [`libgit2`](https://libgit2.org/) — Used for fetching git dependencies. +* [`libssh2`](https://www.libssh2.org/) — Used for SSH access to git repositories. +* [`libz`](https://zlib.net/) (aka zlib) — Used for data compression. + +It is recommended to use the vendored versions as they are the versions that are tested to work with Cargo. + +### Compiling + +First, you'll want to check out this repository + +``` +git clone https://github.com/rust-lang/cargo.git +cd cargo +``` + +With `cargo` already installed, you can simply run: + +``` +cargo build --release +``` + +## Adding new subcommands to Cargo + +Cargo is designed to be extensible with new subcommands without having to modify +Cargo itself. See [the Wiki page][third-party-subcommands] for more details and +a list of known community-developed subcommands. + +[third-party-subcommands]: https://github.com/rust-lang/cargo/wiki/Third-party-cargo-subcommands + + +## Releases + +Cargo releases coincide with Rust releases. +High level release notes are available as part of [Rust's release notes][rel]. +Detailed release notes are available in the [changelog]. + +[rel]: https://github.com/rust-lang/rust/blob/master/RELEASES.md +[changelog]: https://doc.rust-lang.org/nightly/cargo/CHANGELOG.md + +## Reporting issues + +Found a bug? We'd love to know about it! + +Please report all issues on the GitHub [issue tracker][issues]. + +[issues]: https://github.com/rust-lang/cargo/issues + +## Contributing + +See the **[Cargo Contributor Guide]** for a complete introduction +to contributing to Cargo. + +## License + +Cargo is primarily distributed under the terms of both the MIT license +and the Apache License (Version 2.0). + +See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details. + +### Third party software + +This product includes software developed by the OpenSSL Project +for use in the OpenSSL Toolkit (https://www.openssl.org/). + +In binary form, this product includes software that is licensed under the +terms of the GNU General Public License, version 2, with a linking exception, +which can be obtained from the [upstream repository][1]. + +See [LICENSE-THIRD-PARTY](LICENSE-THIRD-PARTY) for details. + +[1]: https://github.com/libgit2/libgit2 + diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/README.md b/collector/compile-benchmarks/cargo-0.87.1/benches/README.md new file mode 100644 index 000000000..900bf084c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/benches/README.md @@ -0,0 +1,157 @@ +# Cargo Benchmarking + +This directory contains some benchmarks for cargo itself. This uses +[Criterion] for running benchmarks. It is recommended to read the Criterion +book to get familiar with how to use it. A basic usage would be: + +```sh +cd benches/benchsuite +cargo bench +``` + +However, running all benchmarks would take many minutes, so in most cases it +is recommended to just run the benchmarks relevant to whatever section of code +you are working on. + +## Benchmarks + +There are several different kinds of benchmarks in the `benchsuite/benches` directory: + +* `global_cache_tracker` — Benchmarks saving data to the global cache tracker + database using samples of real-world data. +* `resolve` — Benchmarks the resolver against simulations of real-world workspaces. +* `workspace_initialization` — Benchmarks initialization of a workspace + against simulations of real-world workspaces. + +### Resolve benchmarks + +The resolve benchmarks involve downloading the index and benchmarking against some +real-world and artificial workspaces located in the [`workspaces`](workspaces) +directory. + +**Beware** that the initial download can take a fairly long amount of time (10 +minutes minimum on an extremely fast network) and require significant disk +space (around 4.5GB). The benchsuite will cache the index and downloaded +crates in the `target/tmp/bench` directory, so subsequent runs should be +faster. You can (and probably should) specify individual benchmarks to run to +narrow it down to a more reasonable set, for example: + +```sh +cargo bench -p benchsuite --bench resolve -- resolve_ws/rust +``` + +This will only download what's necessary for the rust-lang/rust workspace +(which is about 330MB) and run the benchmarks against it (which should take +about a minute). To get a list of all the benchmarks, run: + +```sh +cargo bench -p benchsuite --bench resolve -- --list +``` + +### Global cache tracker + +The `global_cache_tracker` benchmark tests saving data to the global cache +tracker database using samples of real-world data. This benchmark should run +relatively quickly. + +The real-world data is based on a capture of my personal development +environment which has accumulated a large cache. So it is somewhat arbitrary, +but hopefully representative of a challenging environment. Capturing of the +data is done with the `capture-last-use` binary, which you can run if you need +to rebuild the database. Just try to run on a system with a relatively full +cache in your cargo home directory. + +```sh +cargo bench -p benchsuite --bench global_cache_tracker +``` + +## Viewing reports + +The benchmarks display some basic information on the command-line while they +run. A more complete HTML report can be found at +`target/criterion/report/index.html` which contains links to all the +benchmarks and summaries. Check out the Criterion book for more information on +the extensive reporting capabilities. + +## Comparing implementations + +Knowing the raw numbers can be useful, but what you're probably most +interested in is checking if your changes help or hurt performance. To do +that, you need to run the benchmarks multiple times. + +First, run the benchmarks from the master branch of cargo without any changes. +To make it easier to compare, Criterion supports naming the baseline so that +you can iterate on your code and compare against it multiple times. + +```sh +cargo bench -- --save-baseline master +``` + +Now you can switch to your branch with your changes. Re-run the benchmarks +compared against the baseline: + +```sh +cargo bench -- --baseline master +``` + +You can repeat the last command as you make changes to re-compare against the +master baseline. + +Without the baseline arguments, it will compare against the last run, which +can be helpful for comparing incremental changes. + +## Capturing workspaces + +The [`workspaces`](workspaces) directory contains several workspaces that +provide a variety of different workspaces intended to provide good exercises +for benchmarks. Some of these are shadow copies of real-world workspaces. This +is done with the tool in the [`capture`](capture) directory. The tool will +copy `Cargo.lock` and all of the `Cargo.toml` files of the workspace members. +It also adds an empty `lib.rs` so Cargo won't error, and sanitizes the +`Cargo.toml` to some degree, removing unwanted elements. Finally, it +compresses everything into a `tgz`. + +To run it, do: + +```sh +cd benches/capture +cargo run -- /path/to/workspace/foo +``` + +The resolver benchmarks also support the `CARGO_BENCH_WORKSPACES` environment +variable, which you can point to a Cargo workspace if you want to try +different workspaces. For example: + +```sh +CARGO_BENCH_WORKSPACES=/path/to/some/workspace cargo bench +``` + +## TODO + +This is just a start for establishing a benchmarking suite for Cargo. There's +a lot that can be added. Some ideas: + +* Fix the benchmarks so that the resolver setup doesn't run every iteration. +* Benchmark [this section of + code](https://github.com/rust-lang/cargo/blob/a821e2cb24d7b6013433f069ab3bad53d160e100/src/cargo/ops/cargo_compile.rs#L470-L549) + which builds the unit graph. The performance there isn't great, and it would + be good to keep an eye on it. Unfortunately that would mean doing a bit of + work to make `generate_targets` publicly visible, and there is a bunch of + setup code that may need to be duplicated. +* Benchmark the fingerprinting code. +* Benchmark running the `cargo` executable. Running something like `cargo + build` or `cargo check` with everything "Fresh" would be a good end-to-end + exercise to measure the overall overhead of Cargo. +* Benchmark pathological resolver scenarios. There might be some cases where + the resolver can spend a significant amount of time. It would be good to + identify if these exist, and create benchmarks for them. This may require + creating an artificial index, similar to the `resolver-tests`. This should + also consider scenarios where the resolver ultimately fails. +* Benchmark without `Cargo.lock`. I'm not sure if this is particularly + valuable, since we are mostly concerned with incremental builds which will + always have a lock file. +* Benchmark just + [`resolve::resolve`](https://github.com/rust-lang/cargo/blob/a821e2cb24d7b6013433f069ab3bad53d160e100/src/cargo/core/resolver/mod.rs#L122) + without anything else. This can help focus on just the resolver. + +[Criterion]: https://bheisler.github.io/criterion.rs/book/ diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/cargo.tgz b/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/cargo.tgz new file mode 100644 index 0000000000000000000000000000000000000000..653aff982d6061eb8c5c204cef8a55a8b64e49f8 GIT binary patch literal 9967 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 literal 0 HcmV?d00001 diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/empty.tgz b/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/empty.tgz new file mode 100644 index 0000000000000000000000000000000000000000..1a7d555b407ac27e9f3433713c66b152dfc89f75 GIT binary patch literal 287 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ξg*K`ERC{G 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 J&WHdG1pp`mPlW&g literal 0 HcmV?d00001 diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/rust-ws-inherit.tgz b/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/rust-ws-inherit.tgz new file mode 100644 index 0000000000000000000000000000000000000000..6e7b6691ff7643975f2b7bf83800ab3aaebb1781 GIT binary patch literal 45123 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

#vt895sj30o9#c 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 U^S}T6U;oel4|eXv&;W`B05^gpjsO4v literal 0 HcmV?d00001 diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/rust.tgz b/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/rust.tgz new file mode 100644 index 0000000000000000000000000000000000000000..74da4759b02443aa54dead3daaef99843e2a15fb GIT binary patch literal 45064 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 literal 0 HcmV?d00001 diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/substrate.tgz b/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/substrate.tgz new file mode 100644 index 0000000000000000000000000000000000000000..81c3874f6550e83bee285d860ddddb91986d8992 GIT binary patch literal 92972 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 + +The `--build-plan` argument for the `build` command will output JSON with +information about which commands would be run without actually executing +anything. This can be useful when integrating with another build tool. +Example: + +```sh +cargo +nightly build --build-plan -Z unstable-options +``` + +## 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) + +Metabuild is a feature to have declarative build scripts. Instead of writing +a `build.rs` script, you specify a list of build dependencies in the +`metabuild` key in `Cargo.toml`. A build script is automatically generated +that runs each build dependency in order. Metabuild packages can then read +metadata from `Cargo.toml` to specify their behavior. + +Include `cargo-features` at the top of `Cargo.toml`, a `metabuild` key in the +`package`, list the dependencies in `build-dependencies`, and add any metadata +that the metabuild packages require under `package.metadata`. Example: + +```toml +cargo-features = ["metabuild"] + +[package] +name = "mypackage" +version = "0.0.1" +metabuild = ["foo", "bar"] + +[build-dependencies] +foo = "1.0" +bar = "1.0" + +[package.metadata.foo] +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 +* Tracking Issue: [#44663](https://github.com/rust-lang/rust/issues/44663) + +The 'public-dependency' feature allows marking dependencies as 'public' +or 'private'. When this feature is enabled, additional information is passed to rustc to allow +the [exported_private_dependencies](../../rustc/lints/listing/warn-by-default.html#exported-private-dependencies) lint to function properly. + +To enable this feature, you can either use `-Zpublic-dependency` + +```sh +cargo +nightly run -Zpublic-dependency +``` + +or `[unstable]` table, for example, + +```toml +# .cargo/config.toml +[unstable] +public-dependency = true +``` + +`public-dependency` could also be enabled in `cargo-features`, **though this is deprecated and will be removed soon**. + +```toml +cargo-features = ["public-dependency"] + +[dependencies] +my_dep = { version = "1.2.3", public = true } +private_dep = "2.0.0" # Will be 'private' by default +``` + +Documentation updates: +- For workspace's "The `dependencies` table" section, include `public` as an unsupported field for `workspace.dependencies` + +## msrv-policy +- [RFC: MSRV-aware Resolver](https://rust-lang.github.io/rfcs/3537-msrv-resolver.html) +- [#9930](https://github.com/rust-lang/cargo/issues/9930) (MSRV-aware resolver) + +Catch-all unstable feature for MSRV-aware cargo features under +[RFC 2495](https://github.com/rust-lang/rfcs/pull/2495). + +### MSRV-aware cargo add + +This was stabilized in 1.79 in [#13608](https://github.com/rust-lang/cargo/pull/13608). + +### MSRV-aware resolver + +This was stabilized in 1.84 in [#14639](https://github.com/rust-lang/cargo/pull/14639). + +### Convert `incompatible_toolchain` error into a lint + +Unimplemented + +### `--update-rust-version` flag for `cargo add`, `cargo update` + +Unimplemented + +### `package.rust-version = "toolchain"` + +Unimplemented + +### Update `cargo new` template to set `package.rust-version = "toolchain"` + +Unimplemented + +## precise-pre-release + +* Tracking Issue: [#13290](https://github.com/rust-lang/cargo/issues/13290) +* RFC: [#3493](https://github.com/rust-lang/rfcs/pull/3493) + +The `precise-pre-release` feature allows pre-release versions to be selected with `update --precise` +even when a pre-release is not specified by a projects `Cargo.toml`. + +Take for example this `Cargo.toml`. + +```toml +[dependencies] +my-dependency = "0.1.1" +``` + +It's possible to update `my-dependency` to a pre-release with `update -Zunstable-options my-dependency --precise 0.1.2-pre.0`. +This is because `0.1.2-pre.0` is considered compatible with `0.1.1`. +It would not be possible to upgrade to `0.2.0-pre.0` from `0.1.1` in the same way. + +## update-breaking + +* Tracking Issue: [#12425](https://github.com/rust-lang/cargo/issues/12425) + +Allow upgrading dependencies version requirements in `Cargo.toml` across SemVer +incompatible versions using with the `--breaking` flag. + +This only applies to dependencies when +- The package is a dependency of a workspace member +- The dependency is not renamed +- A SemVer-incompatible version is available +- The "SemVer operator" is used (`^` which is the default) + +Users may further restrict which packages get upgraded by specifying them on +the command line. + +Example: +```console +$ cargo +nightly -Zunstable-options update --breaking +$ cargo +nightly -Zunstable-options update --breaking clap +``` + +*This is meant to fill a similar role as [cargo-upgrade](https://github.com/killercup/cargo-edit/)* + +## build-std +* Tracking Repository: + +The `build-std` feature enables Cargo to compile the standard library itself as +part of a crate graph compilation. This feature has also historically been known +as "std-aware Cargo". This feature is still in very early stages of development, +and is also a possible massive feature addition to Cargo. This is a very large +feature to document, even in the minimal form that it exists in today, so if +you're curious to stay up to date you'll want to follow the [tracking +repository](https://github.com/rust-lang/wg-cargo-std-aware) and its set of +issues. + +The functionality implemented today is behind a flag called `-Z build-std`. This +flag indicates that Cargo should compile the standard library from source code +using the same profile as the main build itself. Note that for this to work you +need to have the source code for the standard library available, and at this +time the only supported method of doing so is to add the `rust-src` rust rustup +component: + +```console +$ rustup component add rust-src --toolchain nightly +``` + +Usage looks like: + +```console +$ cargo new foo +$ cd foo +$ cargo +nightly run -Z build-std --target x86_64-unknown-linux-gnu + Compiling core v0.0.0 (...) + ... + Compiling foo v0.1.0 (...) + Finished dev [unoptimized + debuginfo] target(s) in 21.00s + Running `target/x86_64-unknown-linux-gnu/debug/foo` +Hello, world! +``` + +Here we recompiled the standard library in debug mode with debug assertions +(like `src/main.rs` is compiled) and everything was linked together at the end. + +Using `-Z build-std` will implicitly compile the stable crates `core`, `std`, +`alloc`, and `proc_macro`. If you're using `cargo test` it will also compile the +`test` crate. If you're working with an environment which does not support some +of these crates, then you can pass an argument to `-Zbuild-std` as well: + +```console +$ cargo +nightly build -Z build-std=core,alloc +``` + +The value here is a comma-separated list of standard library crates to build. + +### Requirements + +As a summary, a list of requirements today to use `-Z build-std` are: + +* You must install libstd's source code through `rustup component add rust-src` +* 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 + +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 +this is just the beginning. If you'd like to report bugs please either report +them to: + +* Cargo --- --- for implementation bugs +* The tracking repository --- + --- for larger design + questions. + +Also if you'd like to see a feature that's not yet implemented and/or if +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 +* Tracking Repository: + +This flag is a sibling to the `-Zbuild-std` feature flag. This will configure +the features enabled for the standard library itself when building the standard +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 +* 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 +`rustc` which will then cause `rustc` to include the paths of all binary +dependencies in the "dep info" file (with the `.d` extension). Cargo then uses +that information for change-detection (if any binary dependency changes, then +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. + +## checksum-freshness +* Tracking issue: [#14136](https://github.com/rust-lang/cargo/issues/14136) + +The `-Z checksum-freshness` flag will replace the use of file mtimes in cargo's +fingerprints with a file checksum value. This is most useful on systems with a poor +mtime implementation, or in CI/CD. The checksum algorithm can change without notice +between cargo versions. Fingerprints are used by cargo to determine when a crate needs to be rebuilt. + +For the time being files ingested by build script will continue to use mtimes, even when `checksum-freshness` +is enabled. This is not intended as a long term solution. + +## 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) + +The `-Z panic-abort-tests` flag will enable nightly support to compile test +harness crates with `-Cpanic=abort`. Without this flag Cargo will compile tests, +and everything they depend on, with `-Cpanic=unwind` because it's the only way +`test`-the-crate knows how to operate. As of [rust-lang/rust#64158], however, +the `test` crate supports `-C panic=abort` with a test-per-process, and can help +avoid compiling crate graphs multiple times. + +It's currently unclear how this feature will be stabilized in Cargo, but we'd +like to stabilize it somehow! + +[rust-lang/rust#64158]: https://github.com/rust-lang/rust/pull/64158 + +## config-include +* Tracking Issue: [#7723](https://github.com/rust-lang/cargo/issues/7723) + +This feature requires the `-Zconfig-include` command-line option. + +The `include` key in a config file can be used to load another config file. It +takes a string for a path to another file relative to the config file, or an +array of config file paths. Only path ending with `.toml` is accepted. + +```toml +# a path ending with `.toml` +include = "path/to/mordor.toml" + +# or an array of paths +include = ["frodo.toml", "samwise.toml"] +``` + +Unlike other config values, the merge behavior of the `include` key is +different. When a config file contains an `include` key: + +1. The config values are first loaded from the `include` path. + * If the value of the `include` key is an array of paths, the config values + are loaded and merged from left to right for each path. + * Recurse this step if the config values from the `include` path also + contain 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 +* Original Pull Request: [#9322](https://github.com/rust-lang/cargo/pull/9322) +* Tracking Issue: [#9453](https://github.com/rust-lang/cargo/issues/9453) + +Historically, Cargo's behavior for whether the `linker` and `rustflags` +configuration options from environment variables and +[`[target]`](config.md#target) are respected for build scripts, plugins, +and other artifacts that are _always_ built for the host platform has +been somewhat inconsistent. +When `--target` is _not_ passed, Cargo respects the same `linker` and +`rustflags` for build scripts as for all other compile artifacts. When +`--target` _is_ passed, however, Cargo respects `linker` from +[`[target.]`](config.md#targettriplelinker), and does not +pick up any `rustflags` configuration. +This dual behavior is confusing, but also makes it difficult to correctly +configure builds where the host triple and the [target triple] happen to +be the same, but artifacts intended to run on the build host should still +be configured differently. + +`-Ztarget-applies-to-host` enables the top-level +`target-applies-to-host` setting in Cargo configuration files which +allows users to opt into different (and more consistent) behavior for +these properties. When `target-applies-to-host` is unset, or set to +`true`, in the configuration file, the existing Cargo behavior is +preserved (though see `-Zhost-config`, which changes that default). When +it is set to `false`, no options from `[target.]`, +`RUSTFLAGS`, or `[build]` are respected for host artifacts regardless of +whether `--target` is passed to Cargo. To customize artifacts intended +to be run on the host, use `[host]` ([`host-config`](#host-config)). + +In the future, `target-applies-to-host` may end up defaulting to `false` +to provide more sane and consistent default behavior. + +```toml +# config.toml +target-applies-to-host = false +``` + +```console +cargo +nightly -Ztarget-applies-to-host build --target x86_64-unknown-linux-gnu +``` + +## 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) + +The `host` key in a config file can be used to pass flags to host build targets +such as build scripts that must run on the host system instead of the target +system when cross compiling. It supports both generic and host arch specific +tables. Matching host arch tables take precedence over generic host tables. + +It requires the `-Zhost-config` and `-Ztarget-applies-to-host` +command-line options to be set, and that `target-applies-to-host = +false` is set in the Cargo configuration file. + +```toml +# config.toml +[host] +linker = "/path/to/host/linker" +[host.x86_64-unknown-linux-gnu] +linker = "/path/to/host/arch/linker" +rustflags = ["-Clink-arg=--verbose"] +[target.x86_64-unknown-linux-gnu] +linker = "/path/to/target/linker" +``` + +The generic `host` table above will be entirely ignored when building on an +`x86_64-unknown-linux-gnu` host as the `host.x86_64-unknown-linux-gnu` table +takes precedence. + +Setting `-Zhost-config` changes the default for `target-applies-to-host` to +`false` from `true`. + +```console +cargo +nightly -Ztarget-applies-to-host -Zhost-config build --target x86_64-unknown-linux-gnu +``` + +## 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`, +`run`, `test`, `bench`, `doc`, etc.) to emit a JSON object to stdout which +represents Cargo's internal unit graph. Nothing is actually built, and the +command returns immediately after printing. Each "unit" corresponds to an +execution of the compiler. These objects also include which unit each unit +depends on. + +``` +cargo +nightly build --unit-graph -Z unstable-options +``` + +This structure provides a more complete view of the dependency relationship as +Cargo sees it. In particular, the "features" field supports the new feature +resolver where a dependency can be built multiple times with different +features. `cargo metadata` fundamentally cannot represent the relationship of +features between different dependency kinds, and features now depend on which +command is run and which packages and targets are selected. Additionally it +can provide details about intra-package dependencies like build scripts or +tests. + +The following is a description of the JSON structure: + +```javascript +{ + /* Version of the JSON output structure. If any backwards incompatible + changes are made, this value will be increased. + */ + "version": 1, + /* Array of all build units. */ + "units": [ + { + /* An opaque string which indicates the package. + Information about the package can be obtained from `cargo metadata`. + */ + "pkg_id": "my-package 0.1.0 (path+file:///path/to/my-package)", + /* The Cargo target. See the `cargo metadata` documentation for more + information about these fields. + https://doc.rust-lang.org/cargo/commands/cargo-metadata.html + */ + "target": { + "kind": ["lib"], + "crate_types": ["lib"], + "name": "my_package", + "src_path": "/path/to/my-package/src/lib.rs", + "edition": "2018", + "test": true, + "doctest": true + }, + /* The profile settings for this unit. + These values may not match the profile defined in the manifest. + Units can use modified profile settings. For example, the "panic" + setting can be overridden for tests to force it to "unwind". + */ + "profile": { + /* The profile name these settings are derived from. */ + "name": "dev", + /* The optimization level as a string. */ + "opt_level": "0", + /* The LTO setting as a string. */ + "lto": "false", + /* The codegen units as an integer. + `null` if it should use the compiler's default. + */ + "codegen_units": null, + /* The debug information level as an integer. + `null` if it should use the compiler's default (0). + */ + "debuginfo": 2, + /* Whether or not debug-assertions are enabled. */ + "debug_assertions": true, + /* Whether or not overflow-checks are enabled. */ + "overflow_checks": true, + /* Whether or not rpath is enabled. */ + "rpath": false, + /* Whether or not incremental is enabled. */ + "incremental": true, + /* The panic strategy, "unwind" or "abort". */ + "panic": "unwind" + }, + /* Which platform this target is being built for. + A value of `null` indicates it is for the host. + Otherwise it is a string of the target triple (such as + "x86_64-unknown-linux-gnu"). + */ + "platform": null, + /* The "mode" for this unit. Valid values: + + * "test" --- Build using `rustc` as a test. + * "build" --- Build using `rustc`. + * "check" --- Build using `rustc` in "check" mode. + * "doc" --- Build using `rustdoc`. + * "doctest" --- Test using `rustdoc`. + * "run-custom-build" --- Represents the execution of a build script. + */ + "mode": "build", + /* Array of features enabled on this unit as strings. */ + "features": ["somefeat"], + /* Whether or not this is a standard-library unit, + part of the unstable build-std feature. + If not set, treat as `false`. + */ + "is_std": false, + /* Array of dependencies of this unit. */ + "dependencies": [ + { + /* Index in the "units" array for the dependency. */ + "index": 1, + /* The name that this dependency will be referred as. */ + "extern_crate_name": "unicode_xid", + /* Whether or not this dependency is "public", + part of the unstable public-dependency feature. + If not set, the public-dependency feature is not enabled. + */ + "public": false, + /* Whether or not this dependency is injected into the prelude, + currently used by the build-std feature. + If not set, treat as `false`. + */ + "noprelude": false + } + ] + }, + // ... + ], + /* Array of indices in the "units" array that are the "roots" of the + dependency graph. + */ + "roots": [0], +} +``` + +## 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) + +This feature provides a new option in the `[profile]` section to specify flags +that are passed directly to rustc. +This can be enabled like so: + +```toml +cargo-features = ["profile-rustflags"] + +[package] +# ... + +[profile.release] +rustflags = [ "-C", "..." ] +``` + +To set this in a profile in Cargo configuration, you need to use either +`-Z profile-rustflags` or `[unstable]` table to enable it. For example, + +```toml +# .cargo/config.toml +[unstable] +profile-rustflags = true + +[profile.release] +rustflags = [ "-C", "..." ] +``` + +## 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 +it can generate links to dependencies whose documentation is hosted elsewhere +when the dependency is not documented. First, add this to `.cargo/config`: + +```toml +[doc.extern-map.registries] +crates-io = "https://docs.rs/" +``` + +Then, when building documentation, use the following flags to cause links +to dependencies to link to [docs.rs](https://docs.rs/): + +``` +cargo +nightly doc --no-deps -Zrustdoc-map +``` + +The `registries` table contains a mapping of registry name to the URL to link +to. The URL may have the markers `{pkg_name}` and `{version}` which will get +replaced with the corresponding values. If neither are specified, then Cargo +defaults to appending `{pkg_name}/{version}/` to the end of the URL. + +Another config setting is available to redirect standard library links. By +default, rustdoc creates links to . To +change this behavior, use the `doc.extern-map.std` setting: + +```toml +[doc.extern-map] +std = "local" +``` + +A value of `"local"` means to link to the documentation found in the `rustc` +sysroot. If you are using rustup, this documentation can be installed with +`rustup component add rust-docs`. + +The default value is `"remote"`. + +The value may also take a URL for a custom location. + +## 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) + +The `per-package-target` feature adds two keys to the manifest: +`package.default-target` and `package.forced-target`. The first makes +the package be compiled by default (ie. when no `--target` argument is +passed) for some target. The second one makes the package always be +compiled for the target. + +Example: + +```toml +[package] +forced-target = "wasm32-unknown-unknown" +``` + +In this example, the crate is always built for +`wasm32-unknown-unknown`, for instance because it is going to be used +as a plugin for a main program that runs on the host (or provided on +the command line) target. + +## 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) + +Artifact dependencies allow Cargo packages to depend on `bin`, `cdylib`, and `staticlib` crates, +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 adds the following keys to a dependency declaration in `Cargo.toml`: + +- `artifact` --- This specifies the [Cargo Target](cargo-targets.md) to build. + Normally without this field, Cargo will only build the `[lib]` target from a dependency. + This field allows specifying which target will be built, and made available as a binary at build time: + + * `"bin"` --- Compiled executable binaries, corresponding to all of the `[[bin]]` sections in the dependency's manifest. + * `"bin:"` --- Compiled executable binary, corresponding to a specific binary target specified by the given ``. + * `"cdylib"` --- A C-compatible dynamic library, corresponding to a `[lib]` section with `crate-type = ["cdylib"]` in the dependency's manifest. + * `"staticlib"` --- A C-compatible static library, corresponding to a `[lib]` section with `crate-type = ["staticlib"]` in the dependency's manifest. + + The `artifact` value can be a string, or it can be an array of strings to specify multiple targets. + + Example: + + ```toml + [dependencies] + bar = { version = "1.0", artifact = "staticlib" } + zoo = { version = "1.0", artifact = ["bin:cat", "bin:dog"]} + ``` + +- `lib` --- This is a Boolean value which indicates whether or not to also build the dependency's library as a normal Rust `lib` dependency. + This field can only be specified when `artifact` is specified. + + The default for this field is `false` when `artifact` is specified. + If this is set to `true`, then the dependency's `[lib]` target will also be built for the platform target the declaring package is being built for. + This allows the package to use the dependency from Rust code like a normal dependency in addition to an artifact dependency. + + Example: + + ```toml + [dependencies] + bar = { version = "1.0", artifact = "bin", lib = true } + ``` + +- `target` --- The platform target to build the dependency for. + This field can only be specified when `artifact` is specified. + + The default if this is not specified depends on the dependency kind. + For build dependencies, it will be built for the host target. + For all other dependencies, it will be built for the same targets the declaring package is built for. + + For a build dependency, this can also take the special value of `"target"` which means to build the dependency for the same targets that the package is being built for. + + ```toml + [build-dependencies] + bar = { version = "1.0", artifact = "cdylib", target = "wasm32-unknown-unknown"} + same-target = { version = "1.0", artifact = "bin", target = "target" } + ``` + +### artifact-dependencies: Environment variables + +After building an artifact dependency, Cargo provides the following environment variables that you can use to access the artifact: + +- `CARGO__DIR_` --- This is the directory containing all the artifacts from the dependency. + + `` is the `artifact` specified for the dependency (uppercased as in `CDYLIB`, `STATICLIB`, or `BIN`) and `` is the name of the dependency. + As with other Cargo environment variables, dependency names are converted to uppercase, with dashes replaced by underscores. + + If your manifest renames the dependency, `` corresponds to the name you specify, not the original package name. + +- `CARGO__FILE__` --- This is the full path to the artifact. + + `` is the `artifact` specified for the dependency (uppercased as above), `` is the name of the dependency (transformed as above), and `` is the name of the artifact from the dependency. + + Note that `` is not modified in any way from the `name` specified in the crate supplying the artifact, or the crate name if not specified; for instance, it may be in lowercase, or contain dashes. + + For convenience, if the artifact name matches the original package name, cargo additionally supplies a copy of this variable with the `_` suffix omitted. + For instance, if the `cmake` crate supplies a binary named `cmake`, Cargo supplies both `CARGO_BIN_FILE_CMAKE` and `CARGO_BIN_FILE_CMAKE_cmake`. + +For each kind of dependency, these variables are supplied to the same part of the build process that has access to that kind of dependency: + +- For build-dependencies, these variables are supplied to the `build.rs` script, and can be accessed using [`std::env::var_os`](https://doc.rust-lang.org/std/env/fn.var_os.html). + (As with any OS file path, these may or may not be valid UTF-8.) +- For normal dependencies, these variables are supplied during the compilation of the crate, and can be accessed using the [`env!`] macro. +- For dev-dependencies, these variables are supplied during the compilation of examples, tests, and benchmarks, and can be accessed using the [`env!`] macro. + +[`env!`]: https://doc.rust-lang.org/std/macro.env.html + +### artifact-dependencies: Examples + +#### 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: + +```toml +[build-dependencies] +some-build-tool = { version = "1.0", artifact = "bin" } +``` + +Then inside the build script, the binary can be executed at build time: + +```rust +fn main() { + let build_tool = std::env::var_os("CARGO_BIN_FILE_SOME_BUILD_TOOL").unwrap(); + let status = std::process::Command::new(build_tool) + .arg("do-stuff") + .status() + .unwrap(); + if !status.success() { + eprintln!("failed!"); + std::process::exit(1); + } +} +``` + +#### 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… + +```toml +[build-dependencies] +bar = { artifact = "cdylib", version = "1.0", target = "wasm32-unknown-unknown" } +``` + +…along with the build script in `build.rs`. + +```rust +fn main() { + wasm::run_file(std::env::var("CARGO_CDYLIB_FILE_BAR").unwrap()); +} +``` + +#### 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… + +```toml +[dependencies] +bar = { artifact = "bin", version = "1.0", lib = true } +``` + +…along with the executable using `main.rs`. + +```rust +fn main() { + bar::init(); + command::run(env!("CARGO_BIN_FILE_BAR")); +} +``` + +## 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 +`cargo publish` waits between posting a package to the registry and it being +available in the local index. + +A timeout of `0` prevents any checks from occurring. The current default is +`60` seconds. + +It requires the `-Zpublish-timeout` command-line options to be set. + +```toml +# config.toml +[publish] +timeout = 300 # in seconds +``` + +## asymmetric-token +* Tracking Issue: [10519](https://github.com/rust-lang/cargo/issues/10519) +* RFC: [#3231](https://github.com/rust-lang/rfcs/pull/3231) + +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 + +A keypair can be generated with `cargo login --generate-keypair` which will: +- generate a public/private keypair in the currently recommended fashion. +- save the private key in `credentials.toml`. +- print the public key in [PASERK public](https://github.com/paseto-standard/paserk/blob/master/types/public.md) format. + +It is recommended that the `private-key` be saved in `credentials.toml`. It is also supported in `config.toml`, primarily so that it can be set using the associated environment variable, which is the recommended way to provide it in CI contexts. This setup is what we have for the `token` field for setting a secret token. + +There is also an optional field called `private-key-subject` which is a string chosen by the registry. +This string will be included as part of an asymmetric token and should not be secret. +It is intended for the rare use cases like "cryptographic proof that the central CA server authorized this action". Cargo requires it to be non-whitespace printable ASCII. Registries that need non-ASCII data should base64 encode it. + +Both fields can be set with `cargo login --registry=name --private-key --private-key-subject="subject"` which will prompt you to put in the key value. + +A registry can have at most one of `private-key` or `token` set. + +All PASETOs will include `iat`, the current time in ISO 8601 format. Cargo will include the following where appropriate: +- `sub` an optional, non-secret string chosen by the registry that is expected to be claimed with every request. The value will be the `private-key-subject` from the `config.toml` file. +- `mutation` if present, indicates that this request is a mutating operation (or a read-only operation if not present), must be one of the strings `publish`, `yank`, or `unyank`. + - `name` name of the crate related to this request. + - `vers` version string of the crate related to this request. + - `cksum` the SHA256 hash of the crate contents, as a string of 64 lowercase hexadecimal digits, must be present only when `mutation` is equal to `publish` +- `challenge` the challenge string received from a 401/403 from this server this session. Registries that issue challenges must track which challenges have been issued/used and never accept a given challenge more than once within the same validity period (avoiding the need to track every challenge ever issued). + +The "footer" (which is part of the signature) will be a JSON string in UTF-8 and include: +- `url` the RFC 3986 compliant URL where cargo got the config.json file, + - If this is a registry with an HTTP index, then this is the base URL that all index queries are relative to. + - If this is a registry with a GIT index, it is the URL Cargo used to clone the index. +- `kid` the identifier of the private key used to sign the request, using the [PASERK IDs](https://github.com/paseto-standard/paserk/blob/master/operations/ID.md) standard. + +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. + +## `cargo config` + +* Original Issue: [#2362](https://github.com/rust-lang/cargo/issues/2362) +* Tracking Issue: [#9301](https://github.com/rust-lang/cargo/issues/9301) + +The `cargo config` subcommand provides a way to display the configuration +files that cargo loads. It currently includes the `get` subcommand which +can take an optional config value to display. + +```console +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` + +* Tracking Issue: [#9357](https://github.com/rust-lang/cargo/issues/9357) + +`cargo rustc --print=VAL` forwards the `--print` flag to `rustc` in order to +extract information from `rustc`. This runs `rustc` with the corresponding +[`--print`](https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information) +flag, and then immediately exits without compiling. Exposing this as a cargo +flag allows cargo to inject the correct target and RUSTFLAGS based on the +current configuration. + +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 + +* Tracking Issue: [#9778](https://github.com/rust-lang/cargo/issues/9778) +* PR: [#9627](https://github.com/rust-lang/cargo/pull/9627) + +The `different-binary-name` feature allows setting the filename of the binary without having to obey the +restrictions placed on crate names. For example, the crate name must use only `alphanumeric` characters +or `-` or `_`, and cannot be empty. + +The `filename` parameter should **not** include the binary extension, `cargo` will figure out the appropriate +extension and use that for the binary on its own. + +The `filename` parameter is only available in the `[[bin]]` section of the manifest. + +```toml +cargo-features = ["different-binary-name"] + +[package] +name = "foo" +version = "0.0.1" + +[[bin]] +name = "foo" +filename = "007bar" +path = "src/main.rs" +``` + +## scrape-examples + +* RFC: [#3123](https://github.com/rust-lang/rfcs/pull/3123) +* Tracking Issue: [#9910](https://github.com/rust-lang/cargo/issues/9910) + +The `-Z rustdoc-scrape-examples` flag tells Rustdoc to search crates in the current workspace +for calls to functions. Those call-sites are then included as documentation. You can use the flag +like this: + +``` +cargo doc -Z unstable-options -Z rustdoc-scrape-examples +``` + +By default, Cargo will scrape examples from the example targets of packages being documented. +You can individually enable or disable targets from being scraped with the `doc-scrape-examples` flag, such as: + +```toml +# Enable scraping examples from a library +[lib] +doc-scrape-examples = true + +# Disable scraping examples from an example target +[[example]] +name = "my-example" +doc-scrape-examples = false +``` + +**Note on tests:** enabling `doc-scrape-examples` on test targets will not currently have any effect. Scraping +examples from tests is a work-in-progress. + +**Note on dev-dependencies:** documenting a library does not normally require the crate's dev-dependencies. However, +example targets require dev-deps. For backwards compatibility, `-Z rustdoc-scrape-examples` will *not* introduce a +dev-deps requirement for `cargo doc`. Therefore examples will *not* be scraped from example targets under the +following conditions: + +1. No target being documented requires dev-deps, AND +2. At least one crate with targets being documented has dev-deps, AND +3. The `doc-scrape-examples` parameter is unset or false for all `[[example]]` targets. + +If you want examples to be scraped from example targets, then you must not satisfy one of the above conditions. +For example, you can set `doc-scrape-examples` to true for one example target, and that signals to Cargo that +you are ok with dev-deps being build for `cargo doc`. + +## output-format for rustdoc + +* Tracking Issue: [#13283](https://github.com/rust-lang/cargo/issues/13283) + +This flag determines the output format of `cargo rustdoc`, accepting `html` or `json`, providing tools with a way to lean on [rustdoc's experimental JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). + +You can use the flag like this: + +``` +cargo rustdoc -Z unstable-options --output-format json +``` + +## codegen-backend + +The `codegen-backend` feature makes it possible to select the codegen backend used by rustc using a profile. + +Example: + +```toml +[package] +name = "foo" + +[dependencies] +serde = "1.0.117" + +[profile.dev.package.foo] +codegen-backend = "cranelift" +``` + +To set this in a profile in Cargo configuration, you need to use either +`-Z codegen-backend` or `[unstable]` table to enable it. For example, + +```toml +# .cargo/config.toml +[unstable] +codegen-backend = true + +[profile.dev.package.foo] +codegen-backend = "cranelift" +``` + +## gitoxide + +* Tracking Issue: [#11813](https://github.com/rust-lang/cargo/issues/11813) + +With the 'gitoxide' unstable feature, all or the specified git operations will be performed by +the `gitoxide` crate instead of `git2`. + +While `-Zgitoxide` enables all currently implemented features, one can individually select git operations +to run with `gitoxide` with the `-Zgitoxide=operation[,operationN]` syntax. + +Valid operations are the following: + +* `fetch` - All fetches are done with `gitoxide`, which includes git dependencies as well as the crates index. +* `checkout` *(planned)* - checkout the worktree, with support for filters and submodules. + +## git + +* Tracking Issue: [#13285](https://github.com/rust-lang/cargo/issues/13285) + +With the 'git' unstable feature, both `gitoxide` and `git2` will perform shallow fetches of the crate +index and git dependencies. + +While `-Zgit` enables all currently implemented features, one can individually select when to perform +shallow fetches with the `-Zgit=operation[,operationN]` syntax. + +Valid operations are the following: + +* `shallow-index` - perform a shallow clone of the index. +* `shallow-deps` - perform a shallow clone of git dependencies. + +**Details on shallow clones** + +* To enable shallow clones, add `-Zgit=shallow-deps` for fetching git dependencies or `-Zgit=shallow-index` for fetching registry index. +* Shallow-cloned and shallow-checked-out git repositories reside at their own `-shallow` suffixed directories, i.e, + - `~/.cargo/registry/index/*-shallow` + - `~/.cargo/git/db/*-shallow` + - `~/.cargo/git/checkouts/*-shallow` +* 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 and libgit2 are still smart enough to shallow fetch without unshallowing the existing repository. + +## script + +* Tracking Issue: [#12207](https://github.com/rust-lang/cargo/issues/12207) + +Cargo can directly run `.rs` files as: +```console +$ cargo +nightly -Zscript file.rs +``` +where `file.rs` can be as simple as: +```rust +fn main() {} +``` + +A user may optionally specify a manifest in a `cargo` code fence in a module-level comment, like: +````rust +#!/usr/bin/env -S cargo +nightly -Zscript +---cargo +[dependencies] +clap = { version = "4.2", features = ["derive"] } +--- + +use clap::Parser; + +#[derive(Parser, Debug)] +#[clap(version)] +struct Args { + #[clap(short, long, help = "Path to config")] + config: Option, +} + +fn main() { + let args = Args::parse(); + println!("{:?}", args); +} +```` + +### 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 +embedded manifest. There is no required distinguishment for a single-file +`.rs` package from any other `.rs` file. + +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 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 = ` +- `package.edition = ` to avoid always having to add an embedded + manifest at the cost of potentially breaking scripts on rust upgrades + - Warn when `edition` is unspecified to raise awareness of this + +Disallowed manifest fields: +- `[workspace]`, `[lib]`, `[[bin]]`, `[[example]]`, `[[test]]`, `[[bench]]` +- `package.workspace`, `package.build`, `package.links`, `package.autolib`, `package.autobins`, `package.autoexamples`, `package.autotests`, `package.autobenches` + +The default `CARGO_TARGET_DIR` for single-file packages is at `$CARGO_HOME/target/`: +- Avoid conflicts from multiple single-file packages being in the same directory +- Avoid problems with the single-file package's parent directory being read-only +- Avoid cluttering the user's directory + +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 + +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 +intended for being put in `#!` lines. + +The precedence for how to interpret `cargo ` is +1. Built-in xor single-file packages +2. Aliases +3. External subcommands + +A parameter is identified as a manifest-command if it has one of: +- Path separators +- A `.rs` extension +- The file name is `Cargo.toml` + +Differences between `cargo run --manifest-path ` and `cargo ` +- `cargo ` runs with the config for `` and not the current dir, more like `cargo install --path ` +- `cargo ` is at a verbosity level below the normal default. Pass `-v` to get normal output. + +### Documentation Updates + +## Profile `trim-paths` option + +* Tracking Issue: [rust-lang/cargo#12137](https://github.com/rust-lang/cargo/issues/12137) +* Tracking Rustc Issue: [rust-lang/rust#111540](https://github.com/rust-lang/rust/issues/111540) + +This adds a new profile setting to control how paths are sanitized in the resulting binary. +This can be enabled like so: + +```toml +cargo-features = ["trim-paths"] + +[package] +# ... + +[profile.release] +trim-paths = ["diagnostics", "object"] +``` + +To set this in a profile in Cargo configuration, +you need to use either `-Z trim-paths` or `[unstable]` table to enable it. +For example, + +```toml +# .cargo/config.toml +[unstable] +trim-paths = true + +[profile.release] +trim-paths = ["diagnostics", "object"] +``` + +### Documentation updates + +#### trim-paths + +*as a new ["Profiles settings" entry](./profiles.html#profile-settings)* + +`trim-paths` is a profile setting which enables and controls the sanitization of file paths in build outputs. +It takes the following values: + +- `"none"` and `false` --- disable path sanitization +- `"macro"` --- sanitize paths in the expansion of `std::file!()` macro. + This is where paths in embedded panic messages come from +- `"diagnostics"` --- sanitize paths in printed compiler diagnostics +- `"object"` --- sanitize paths in compiled executables or libraries +- `"all"` and `true` --- sanitize paths in all possible locations + +It also takes an array with the combinations of `"macro"`, `"diagnostics"`, and `"object"`. + +It is defaulted to `none` for the `dev` profile, and `object` for the `release` profile. +You can manually override it by specifying this option in `Cargo.toml`: + +```toml +[profile.dev] +trim-paths = "all" + +[profile.release] +trim-paths = ["object", "diagnostics"] +``` + +The default `release` profile setting (`object`) sanitizes only the paths in emitted executable or library files. +It always affects paths from macros such as panic messages, and in debug information only if they will be embedded together with the binary +(the default on platforms with ELF binaries, such as Linux and windows-gnu), +but will not touch them if they are in separate files (the default on Windows MSVC and macOS). +But the paths to these separate files are sanitized. + +If `trim-paths` is not `none` or `false`, then the following paths are sanitized if they appear in a selected scope: + +1. Path to the source files of the standard and core library (sysroot) will begin with `/rustc/[rustc commit hash]`, + e.g. `/home/username/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs` -> + `/rustc/fe72845f7bb6a77b9e671e6a4f32fe714962cec4/library/core/src/result.rs` +2. Path to the current package will be stripped, relatively to the current workspace root, e.g. `/home/username/crate/src/lib.rs` -> `src/lib.rs`. +3. Path to dependency packages will be replaced with `[package name]-[version]`. E.g. `/home/username/deps/foo/src/lib.rs` -> `foo-0.1.0/src/lib.rs` + +When a path to the source files of the standard and core library is *not* in scope for sanitization, +the emitted path will depend on if `rust-src` component is present. +If it is, then some paths will point to the copy of the source files on your file system; +if it isn't, then they will show up as `/rustc/[rustc commit hash]/library/...` +(just like when it is selected for sanitization). +Paths to all other source files will not be affected. + +This will not affect any hard-coded paths in the source code, such as in strings. + +#### Environment variable + +*as a new entry of ["Environment variables Cargo sets for build scripts"](./environment-variables.md#environment-variables-cargo-sets-for-crates)* + +* `CARGO_TRIM_PATHS` --- The value of `trim-paths` profile option. + `false`, `"none"`, and empty arrays would be converted to `none`. + `true` and `"all"` become `all`. + Values in a non-empty array would be joined into a comma-separated list. + If the build script introduces absolute paths to built artifacts (such as by invoking a compiler), + the user may request them to be sanitized in different types of artifacts. + Common paths requiring sanitization include `OUT_DIR`, `CARGO_MANIFEST_DIR` and `CARGO_MANIFEST_PATH`, + plus any other introduced by the build script, such as include directories. + +## gc + +* Tracking Issue: [#12633](https://github.com/rust-lang/cargo/issues/12633) + +The `-Zgc` flag enables garbage-collection within cargo's global cache within the cargo home directory. +This includes downloaded dependencies such as compressed `.crate` files, extracted `src` directories, registry index caches, and git dependencies. +When `-Zgc` is present, cargo will track the last time any index and dependency was used, +and then uses those timestamps to manually or automatically delete cache entries that have not been used for a while. + +```sh +cargo build -Zgc +``` + +### Automatic garbage collection + +Automatic deletion happens on commands that are already doing a significant amount of work, +such as all of the build commands (`cargo build`, `cargo test`, `cargo check`, etc.), and `cargo fetch`. +The deletion happens just after resolution and packages have been downloaded. +Automatic deletion is only done once per day (see `gc.auto.frequency` to configure). +Automatic deletion is disabled if cargo is offline such as with `--offline` or `--frozen` to avoid deleting artifacts that may need to be used if you are offline for a long period of time. + +#### Automatic gc configuration + +The automatic gc behavior can be specified via a cargo configuration setting. +The settings available are: + +```toml +# Example config.toml file. + +# This table defines the behavior for automatic garbage collection. +[gc.auto] +# The maximum frequency that automatic garbage collection happens. +# Can be "never" to disable automatic-gc, or "always" to run on every command. +frequency = "1 day" +# Anything older than this duration will be deleted in the source cache. +max-src-age = "1 month" +# Anything older than this duration will be deleted in the compressed crate cache. +max-crate-age = "3 months" +# Any index older than this duration will be deleted from the index cache. +max-index-age = "3 months" +# Any git checkout older than this duration will be deleted from the checkout cache. +max-git-co-age = "1 month" +# Any git clone older than this duration will be deleted from the git cache. +max-git-db-age = "3 months" +``` + +### Manual garbage collection with `cargo clean` + +Manual deletion can be done with the `cargo clean gc` command. +Deletion of cache contents can be performed by passing one of the cache options: + +- `--max-src-age=DURATION` --- Deletes source cache files that have not been used since the given age. +- `--max-crate-age=DURATION` --- Deletes crate cache files that have not been used since the given age. +- `--max-index-age=DURATION` --- Deletes registry indexes that have not been used since then given age (including their `.crate` and `src` files). +- `--max-git-co-age=DURATION` --- Deletes git dependency checkouts that have not been used since then given age. +- `--max-git-db-age=DURATION` --- Deletes git dependency clones that have not been used since then given age. +- `--max-download-age=DURATION` --- Deletes any downloaded cache data that has not been used since then given age. +- `--max-src-size=SIZE` --- Deletes the oldest source cache files until the cache is under the given size. +- `--max-crate-size=SIZE` --- Deletes the oldest crate cache files until the cache is under the given size. +- `--max-git-size=SIZE` --- Deletes the oldest git dependency caches until the cache is under the given size. +- `--max-download-size=SIZE` --- Deletes the oldest downloaded cache data until the cache is under the given size. + +A DURATION is specified in the form "N seconds/minutes/days/weeks/months" where N is an integer. + +A SIZE is specified in the form "N *suffix*" where *suffix* is B, kB, MB, GB, kiB, MiB, or GiB, and N is an integer or floating point number. If no suffix is specified, the number is the number of bytes. + +```sh +cargo clean gc +cargo clean gc --max-download-age=1week +cargo clean gc --max-git-size=0 --max-download-size=100MB +``` + +## open-namespaces + +* Tracking Issue: [#13576](https://github.com/rust-lang/cargo/issues/13576) + +Allow multiple packages to participate in the same API namespace + +This can be enabled like so: +```toml +cargo-features = ["open-namespaces"] + +[package] +# ... +``` + +## `[lints.cargo]` + +* Tracking Issue: [#12235](https://github.com/rust-lang/cargo/issues/12235) + +A new `lints` tool table for `cargo` that can be used to configure lints emitted +by `cargo` itself when `-Zcargo-lints` is used +```toml +[lints.cargo] +implicit-features = "warn" +``` + +This will work with +[RFC 2906 `workspace-deduplicate`](https://rust-lang.github.io/rfcs/2906-cargo-workspace-deduplicate.html): +```toml +[workspace.lints.cargo] +implicit-features = "warn" + +[lints] +workspace = true +``` + +## Path Bases + +* Tracking Issue: [#14355](https://github.com/rust-lang/cargo/issues/14355) + +A `path` dependency may optionally specify a base by setting the `base` key to +the name of a path base from the `[path-bases]` table in either the +[configuration](config.md) or one of the [built-in path bases](#built-in-path-bases). +The value of that path base is prepended to the `path` value (along with a path +separator if necessary) to produce the actual location where Cargo will look for +the dependency. + +For example, if the `Cargo.toml` contains: + +```toml +cargo-features = ["path-bases"] + +[dependencies] +foo = { base = "dev", path = "foo" } +``` + +Given a `[path-bases]` table in the configuration that contains: + +```toml +[path-bases] +dev = "/home/user/dev/rust/libraries/" +``` + +This will produce a `path` dependency `foo` located at +`/home/user/dev/rust/libraries/foo`. + +Path bases can be either absolute or relative. Relative path bases are relative +to the parent directory of the configuration file that declared that path base. + +The name of a path base must use only [alphanumeric](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphanumeric) +characters or `-` or `_`, must start with an [alphabetic](https://doc.rust-lang.org/std/primitive.char.html#method.is_alphabetic) +character, and must not be empty. + +If the name of path base used in a dependency is neither in the configuration +nor one of the built-in path base, then Cargo will raise an error. + +#### Built-in path bases + +Cargo provides implicit path bases that can be used without the need to specify +them in a `[path-bases]` table. + +* `workspace` - If a project is [a workspace or workspace member](workspaces.md) +then this path base is defined as the parent directory of the root `Cargo.toml` +of the workspace. + +If a built-in path base name is also declared in the configuration, then Cargo +will prefer the value in the configuration. The allows Cargo to add new built-in +path bases without compatibility issues (as existing uses will shadow the +built-in name). + +## lockfile-path +* Original Issue: [#5707](https://github.com/rust-lang/cargo/issues/5707) +* Tracking Issue: [#14421](https://github.com/rust-lang/cargo/issues/14421) + +This feature allows you to specify the path of lockfile Cargo.lock. +By default, lockfile is written into `/Cargo.lock`. +However, when sources are stored in read-only directory, most of the cargo commands +would fail, trying to write a lockfile. The `--lockfile-path` +flag makes it easier to work with readonly sources. +Note, that currently path must end with `Cargo.lock`. Meaning, if you want to use +this feature in multiple projects, lockfiles should be stored in different directories. +Example: + +```sh +cargo +nightly metadata --lockfile-path=$LOCKFILES_ROOT/my-project/Cargo.lock -Z unstable-options +``` + +## package-workspace +* Tracking Issue: [#10948](https://github.com/rust-lang/cargo/issues/10948) + +This allows cargo to package (or publish) multiple crates in a workspace, even +if they have inter-dependencies. For example, consider a workspace containing +packages `foo` and `dep`, where `foo` depends on `dep`. Then + +```sh +cargo +nightly -Zpackage-workspace package -p foo -p dep +``` + +will package both `foo` and `dep`, while + +```sh +cargo +nightly -Zpackage-workspace publish -p foo -p dep +``` + +will publish both `foo` and `dep`. +If `foo` and `dep` are the only crates in the workspace, you can use the `--workspace` +flag instead of specifying the crates individually: + +```sh +cargo +nightly -Zpackage-workspace package --workspace +cargo +nightly -Zpackage-workspace publish --workspace +``` + +#### Lock-file behavior + +When packaging a binary at the same time as one of its dependencies, the binary +will be packaged with a lock-file pointing at the dependency's registry entry +*as though the dependency were already published*, even though it has not yet +been. In this case, `cargo` needs to know the registry that the dependency +will eventually be published on. `cargo` will attempt to infer this registry +by examining the [the `publish` field](manifest.md#the-publish-field), falling back +to `crates.io` if no `publish` field is set. To explicitly set the registry, +pass a `--registry` or `--index` flag. + +```sh +cargo +nightly -Zpackage-workspace --registry=my-registry package -p foo -p dep +cargo +nightly -Zpackage-workspace --index=https://example.com package -p foo -p dep +``` + +## native-completions +* Original Issue: [#6645](https://github.com/rust-lang/cargo/issues/6645) +* Tracking Issue: [#14520](https://github.com/rust-lang/cargo/issues/14520) + +This feature moves the handwritten completion scripts to Rust native, making it +easier for us to add, extend and test new completions. This feature is enabled with the +nightly channel, without requiring additional `-Z` options. + +Areas of particular interest for feedback +- Arguments that need escaping or quoting that aren't handled correctly +- Inaccuracies in the information +- Bugs in parsing of the command-line +- Arguments that don't report their completions +- If a known issue is being problematic + +Feedback can be broken down into +- What completion candidates are reported + - Known issues: [#14520](https://github.com/rust-lang/cargo/issues/14520), [`A-completions`](https://github.com/rust-lang/cargo/labels/A-completions) + - [Report an issue](https://github.com/rust-lang/cargo/issues/new) or [discuss the behavior](https://github.com/rust-lang/cargo/issues/14520) +- Shell integration, command-line parsing, and completion filtering + - Known issues: [clap#3166](https://github.com/clap-rs/clap/issues/3166), [clap's `A-completions`](https://github.com/clap-rs/clap/labels/A-completion) + - [Report an issue](https://github.com/clap-rs/clap/issues/new/choose) or [discuss the behavior](https://github.com/clap-rs/clap/discussions/new/choose) + +When in doubt, you can discuss this in [#14520](https://github.com/rust-lang/cargo/issues/14520) or on [zulip](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo) + +### How to use native-completions feature: +- bash: + Add `source <(CARGO_COMPLETE=bash cargo +nightly)` to your .bashrc. + +- zsh: + Add `source <(CARGO_COMPLETE=zsh cargo +nightly)` to your .zshrc. + +- fish: + Add `source (CARGO_COMPLETE=fish cargo +nightly | psub)` to `$XDG_CONFIG_HOME/fish/completions/cargo.fish` + +- elvish: + Add `eval (E:CARGO_COMPLETE=elvish cargo +nightly | slurp)` to `$XDG_CONFIG_HOME/elvish/rc.elv` + +- powershell: + Add `CARGO_COMPLETE=powershell cargo +nightly | Invoke-Expression` to `$PROFILE`. + +## warnings + +* Original Issue: [#8424](https://github.com/rust-lang/cargo/issues/8424) +* Tracking Issue: [#14802](https://github.com/rust-lang/cargo/issues/14802) + +The `-Z warnings` feature enables the `build.warnings` configuration option to control how +Cargo handles warnings. If the `-Z warnings` unstable flag is not enabled, then +the `build.warnings` config will be ignored. + +This setting currently only applies to rustc warnings. It may apply to additional warnings (such as Cargo lints or Cargo warnings) +in the future. + +### `build.warnings` +* Type: string +* Default: `warn` +* Environment: `CARGO_BUILD_WARNINGS` + +Controls how Cargo handles warnings. Allowed values are: +* `warn`: warnings are emitted as warnings (default). +* `allow`: warnings are hidden. +* `deny`: if warnings are emitted, an error will be raised at the end of the operation and the process will exit with a failure exit code. +# Stabilized and removed features + +## 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 + +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 + +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 + +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 + +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 + +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 +package contains a binary target. `cargo install` requires the `--locked` flag +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 + +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 + +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 + +The `install-upgrade` feature has been stabilized in the 1.41 release. +[`cargo install`] will now automatically upgrade packages if they appear to be +out-of-date. See the [`cargo install`] documentation for more information. + +[`cargo install`]: ../commands/cargo-install.md + +## 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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 have been stabilized in the 1.57 release. See the +[profiles chapter](profiles.md#custom-profiles) for more information. + +## 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 + +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 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 has been stabilized in the 1.60 release. +See the [Features chapter](features.md#dependency-features) for more information. + +## 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 + +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 + +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 + +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 has been stabilized in the 1.64 release. +See [workspace.package](workspaces.md#the-package-table), +[workspace.dependencies](workspaces.md#the-dependencies-table), +and [inheriting-a-dependency-from-a-workspace](specifying-dependencies.md#inheriting-a-dependency-from-a-workspace) +for more information. + +## 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 support has been stabilized in the 1.68 release. +See [Registry Protocols](registries.md#registry-protocols) for more information. + +### `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` + +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. + +## check-cfg + +The `-Z check-cfg` feature has been stabilized in the 1.80 release by making it the +default behavior. + +See the [build script documentation](build-scripts.md#rustc-check-cfg) for information +about specifying custom cfgs. + +## Edition 2024 + +The 2024 edition has been stabilized in the 1.85 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. + diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/workspaces.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/workspaces.md new file mode 100644 index 000000000..4bdbf3b29 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/workspaces.md @@ -0,0 +1,315 @@ +# Workspaces + +A *workspace* is a collection of one or more packages, called *workspace +members*, that are managed together. + +The key points of workspaces are: + +* Common commands can run across all workspace members, like `cargo check --workspace`. +* All packages share a common [`Cargo.lock`] file which resides in the + *workspace root*. +* All packages share a common [output directory], which defaults to a + directory named `target` in the *workspace root*. +* Sharing package metadata, like with [`workspace.package`](#the-package-table). +* The [`[patch]`][patch], [`[replace]`][replace] and [`[profile.*]`][profiles] + sections in `Cargo.toml` are only recognized in the *root* manifest, and + ignored in member crates' manifests. + +The root `Cargo.toml` of a workspace supports the following sections: + +* [`[workspace]`](#the-workspace-section) --- Defines a workspace. + * [`resolver`](resolver.md#resolver-versions) --- Sets the dependency resolver to use. + * [`members`](#the-members-and-exclude-fields) --- Packages to include in the workspace. + * [`exclude`](#the-members-and-exclude-fields) --- Packages to exclude from the workspace. + * [`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 + +To create a workspace, you add the `[workspace]` table to a `Cargo.toml`: +```toml +[workspace] +# ... +``` + +At minimum, a workspace has to have a member, either with a root package or as +a virtual manifest. + +### Root package + +If the [`[workspace]` section](#the-workspace-section) is added to a +`Cargo.toml` that already defines a `[package]`, the package is +the *root package* of the workspace. The *workspace root* is the directory +where the workspace's `Cargo.toml` is located. + +```toml +[workspace] + +[package] +name = "hello_world" # the name of the package +version = "0.1.0" # the current version, obeying semver +``` + +### 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 +manifest*. This is typically useful when there isn't a "primary" package, or +you want to keep all the packages organized in separate directories. + +```toml +# [PROJECT_DIR]/Cargo.toml +[workspace] +members = ["hello_world"] +resolver = "2" +``` + +```toml +# [PROJECT_DIR]/hello_world/Cargo.toml +[package] +name = "hello_world" # the name of the package +version = "0.1.0" # the current version, obeying semver +edition = "2024" # the edition, will have no effect on a resolver used in the workspace +``` + +By having a workspace without a root package, + +- [`resolver`](resolver.md#resolver-versions) must be + set explicitly in virtual workspaces as they have no + [`package.edition`][package-edition] to infer it from + [resolver version](resolver.md#resolver-versions). +- Commands run in the workspace root will run against all workspace + members by default, see [`default-members`](#the-default-members-field). + +## The `members` and `exclude` fields + +The `members` and `exclude` fields define which packages are members of +the workspace: + +```toml +[workspace] +members = ["member1", "path/to/member2", "crates/*"] +exclude = ["crates/foo", "path/to/other"] +``` + +All [`path` dependencies] residing in the workspace directory automatically +become members. Additional members can be listed with the `members` key, which +should be an array of strings containing directories with `Cargo.toml` files. + +The `members` list also supports [globs] to match multiple paths, using +typical filename glob patterns like `*` and `?`. + +The `exclude` key can be used to prevent paths from being included in a +workspace. This can be useful if some path dependencies aren't desired to be +in the workspace at all, or using a glob pattern and you want to remove a +directory. + +When inside a subdirectory within the workspace, Cargo will automatically +search the parent directories for a `Cargo.toml` file with a `[workspace]` +definition to determine which workspace to use. The [`package.workspace`] +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 + +In a workspace, package-related Cargo commands like [`cargo build`] can use +the `-p` / `--package` or `--workspace` command-line flags to determine which +packages to operate on. If neither of those flags are specified, Cargo will +use the package in the current working directory. However, if the current directory is +a workspace root, the [`default-members`](#the-default-members-field) will be used. + +## The `default-members` field + +The `default-members` field specifies paths of [members](#the-members-and-exclude-fields) to +operate on when in the workspace root and the package selection flags are not +used: + +```toml +[workspace] +members = ["path/to/member1", "path/to/member2", "path/to/member3/*"] +default-members = ["path/to/member2", "path/to/member3/foo"] +``` + +> Note: when a [root package](#root-package) is present, +> you can only operate on it using `--package` and `--workspace` flags. + +When unspecified, the [root package](#root-package) will be used. +In the case of a [virtual workspace](#virtual-workspace), all members will be used +(as if `--workspace` were specified on the command-line). + +## 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 +defining them in the member package with `{key}.workspace = true`. + +Keys that are supported: + +| | | +|----------------|-----------------| +| `authors` | `categories` | +| `description` | `documentation` | +| `edition` | `exclude` | +| `homepage` | `include` | +| `keywords` | `license` | +| `license-file` | `publish` | +| `readme` | `repository` | +| `rust-version` | `version` | + +- `license-file` and `readme` are relative to the workspace root +- `include` and `exclude` are relative to your package root + +Example: +```toml +# [PROJECT_DIR]/Cargo.toml +[workspace] +members = ["bar"] + +[workspace.package] +version = "1.2.3" +authors = ["Nice Folks"] +description = "A short description of my package" +documentation = "https://example.com/bar" +``` + +```toml +# [PROJECT_DIR]/bar/Cargo.toml +[package] +name = "bar" +version.workspace = true +authors.workspace = true +description.workspace = true +documentation.workspace = true +``` + +> **MSRV:** Requires 1.64+ + +## The `dependencies` table + +The `workspace.dependencies` table is where you define dependencies to be +inherited by members of a workspace. + +Specifying a workspace dependency is similar to [package dependencies][specifying-dependencies] except: +- Dependencies from this table cannot be declared as `optional` +- [`features`][features] declared in this table are additive with the `features` from `[dependencies]` + +You can then [inherit the workspace dependency as a package dependency][inheriting-a-dependency-from-a-workspace] + +Example: +```toml +# [PROJECT_DIR]/Cargo.toml +[workspace] +members = ["bar"] + +[workspace.dependencies] +cc = "1.0.73" +rand = "0.8.5" +regex = { version = "1.6.0", default-features = false, features = ["std"] } +``` + +```toml +# [PROJECT_DIR]/bar/Cargo.toml +[package] +name = "bar" +version = "0.2.0" + +[dependencies] +regex = { workspace = true, features = ["unicode"] } + +[build-dependencies] +cc.workspace = true + +[dev-dependencies] +rand.workspace = true +``` + +> **MSRV:** Requires 1.64+ + +## 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](manifest.md#the-lints-section). + +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 +``` + +> **MSRV:** Respected as of 1.74 + +## 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 +configuration in `Cargo.toml`. For example: + +```toml +[workspace] +members = ["member1", "member2"] + +[workspace.metadata.webcontents] +root = "path/to/webproject" +tool = ["npm", "run", "build"] +# ... +``` + +There is a similar set of tables at the package level at +[`package.metadata`][package-metadata]. While cargo does not specify a +format for the content of either of these tables, it is suggested that +external tools may wish to use them in a consistent fashion, such as referring +to the data in `workspace.metadata` if data is missing from `package.metadata`, +if that makes sense for the tool in question. + +[package]: manifest.md#the-package-section +[`Cargo.lock`]: ../guide/cargo-toml-vs-cargo-lock.md +[package-metadata]: manifest.md#the-metadata-table +[package-edition]: manifest.md#the-edition-field +[output directory]: build-cache.md +[patch]: overriding-dependencies.md#the-patch-section +[replace]: overriding-dependencies.md#the-replace-section +[profiles]: profiles.md +[`path` dependencies]: specifying-dependencies.md#specifying-path-dependencies +[`package.workspace`]: manifest.md#the-workspace-field +[globs]: https://docs.rs/glob/0.3.0/glob/struct.Pattern.html +[`cargo build`]: ../commands/cargo-build.md +[specifying-dependencies]: specifying-dependencies.md +[features]: features.md +[inheriting-a-dependency-from-a-workspace]: specifying-dependencies.md#inheriting-a-dependency-from-a-workspace + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/theme/favicon.png b/collector/compile-benchmarks/cargo-0.87.1/src/doc/theme/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..47c8f628fe6072875c5ef1f593a14ca5b3a1143d GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/theme/head.hbs b/collector/compile-benchmarks/cargo-0.87.1/src/doc/theme/head.hbs new file mode 100644 index 000000000..062417e11 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/theme/head.hbs @@ -0,0 +1,5 @@ + diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/_cargo b/collector/compile-benchmarks/cargo-0.87.1/src/etc/_cargo new file mode 100644 index 000000000..12aab736b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/_cargo @@ -0,0 +1,479 @@ +#compdef cargo + +autoload -U regexp-replace + +_cargo() { + local curcontext="$curcontext" ret=1 + local -a command_scope_spec common parallel features msgfmt triple target registry + local -a state line state_descr # These are set by _arguments + typeset -A opt_args + + common=( + '(-q --quiet)*'{-v,--verbose}'[use verbose output]' + '(-q --quiet -v --verbose)'{-q,--quiet}'[no output printed to stdout]' + '-Z+[pass unstable (nightly-only) flags to cargo]: :_cargo_unstable_flags' + '--frozen[require that Cargo.lock and cache are up-to-date]' + '--locked[require that Cargo.lock is up-to-date]' + '--color=[specify colorization option]:coloring:(auto always never)' + '(- 1 *)'{-h,--help}'[show help message]' + ) + + # leading items in parentheses are an exclusion list for the arguments following that arg + # See: http://zsh.sourceforge.net/Doc/Release/Completion-System.html#Completion-Functions + # - => exclude all other options + # 1 => exclude positional arg 1 + # * => exclude all other args + # +blah => exclude +blah + _arguments -s -S -C $common \ + '(- 1 *)--list[list installed commands]' \ + '(- 1 *)--explain=[provide a detailed explanation of an error message]:error code' \ + '(- 1 *)'{-V,--version}'[show version information]' \ + '(+beta +nightly)+stable[use the stable toolchain]' \ + '(+stable +nightly)+beta[use the beta toolchain]' \ + '(+stable +beta)+nightly[use the nightly toolchain]' \ + '1: :_cargo_cmds' \ + '*:: :->args' + + # These flags are mutually exclusive specifiers for the scope of a command; as + # they are used in multiple places without change, they are expanded into the + # appropriate command's `_arguments` where appropriate. + command_scope_spec=( + '(--bin --example --test --lib)--bench=[specify benchmark name]: :_cargo_benchmark_names' + '(--bench --bin --test --lib)--example=[specify example name]:example name:_cargo_example_names' + '(--bench --example --test --lib)--bin=[specify binary name]:binary name' + '(--bench --bin --example --test)--lib=[specify library name]:library name' + '(--bench --bin --example --lib)--test=[specify test name]:test name' + ) + + jobs=( + '(-j --jobs)'{-j+,--jobs=}'[specify number of parallel jobs]:jobs [# of CPUs]' + ) + + parallel=( + "${jobs[@]}" + '--keep-going[do not abort build on first build error]' + ) + + features=( + '(--all-features)'{-F+,--features=}'[specify features to activate]:feature' + '(--features -F)--all-features[activate all available features]' + "--no-default-features[don't build the default features]" + ) + + msgfmt='--message-format=[specify error format]:error format [human]:(human json short)' + triple='--target=[specify target triple]:target triple:_cargo_target_triple' + target='--target-dir=[specify directory for all generated artifacts]:directory:_directories' + manifest='--manifest-path=[specify path to manifest]:path:_directories' + registry='--registry=[specify registry to use]:registry' + + case $state in + args) + curcontext="${curcontext%:*}-${words[1]}:" + case ${words[1]} in + add) + _arguments -s -A "^--" $common $manifest $registry \ + {-F+,--features=}'[specify features to activate]:feature' \ + "--default-features[enable the default features]" \ + "--no-default-features[don't enable the default features]" \ + "--optional[mark the dependency as optional]" \ + "--no-optional[mark the dependency as required]" \ + "--dev[add as a dev dependency]" \ + "--build[add as a build dependency]" \ + "--target=[add as a dependency to the given target platform]" \ + "--rename=[rename the dependency]" \ + "--dry-run[don't actually write the manifest]" \ + '--branch=[branch to use when adding from git]:branch' \ + '--git=[specify URL from which to add the crate]:url:_urls' \ + '--path=[local filesystem path to crate to add]: :_directories' \ + '--rev=[specific commit to use when adding from git]:commit' \ + '--tag=[tag to use when adding from git]:tag' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' \ + '1: :_guard "^-*" "crate name"' \ + '*:args:_default' + ;; + bench) + _arguments -s -A "^--" $common $jobs $features $msgfmt $triple $target $manifest \ + "${command_scope_spec[@]}" \ + '--all-targets[benchmark all targets]' \ + "--no-run[compile but don't run]" \ + '(-p --package)'{-p+,--package=}'[specify package to run benchmarks for]:package:_cargo_package_names' \ + '--exclude=[exclude packages from the benchmark]:spec' \ + '--no-fail-fast[run all benchmarks regardless of failure]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' \ + '1: :_guard "^-*" "bench name"' \ + '*:args:_default' + ;; + + build | b) + _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \ + '--all-targets[equivalent to specifying --lib --bins --tests --benches --examples]' \ + "${command_scope_spec[@]}" \ + '(-p --package)'{-p+,--package=}'[specify package to build]:package:_cargo_package_names' \ + '--release[build in release mode]' \ + '--build-plan[output the build plan in JSON]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' + ;; + + check | c) + _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \ + '--all-targets[equivalent to specifying --lib --bins --tests --benches --examples]' \ + "${command_scope_spec[@]}" \ + '(-p --package)'{-p+,--package=}'[specify package to check]:package:_cargo_package_names' \ + '--release[check in release mode]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' + ;; + + clean) + _arguments -s -S $common $triple $target $manifest \ + '(-p --package)'{-p+,--package=}'[specify package to clean]:package:_cargo_package_names' \ + '--release[clean release artifacts]' \ + '--doc[clean just the documentation directory]' + ;; + + doc | d) + _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \ + '--no-deps[do not build docs for dependencies]' \ + '--document-private-items[include non-public items in the documentation]' \ + '--open[open docs in browser after the build]' \ + '(-p --package)'{-p+,--package=}'[specify package to document]:package:_cargo_package_names' \ + '--release[build artifacts in release mode, with optimizations]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' + ;; + + fetch) + _arguments -s -S $common $triple $manifest + ;; + + fix) + _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \ + "${command_scope_spec[@]}" \ + '--broken-code[fix code even if it already has compiler errors]' \ + '--edition[fix in preparation for the next edition]' \ + '--edition-idioms[fix warnings to migrate to the idioms of an edition]' \ + '--allow-no-vcs[fix code even if a VCS was not detected]' \ + '--allow-dirty[fix code even if the working directory is dirty]' \ + '--allow-staged[fix code even if the working directory has staged changes]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' + ;; + + generate-lockfile) + _arguments -s -S $common $manifest + ;; + + help) + _cargo_cmds + ;; + info) + _arguments -s -A "^--" $common $registry \ + '--index=[specify registry index]:index' \ + '*: :_guard "^-*" "crate"' + ;; + + init) + _arguments -s -S $common $registry \ + '--lib[use library template]' \ + '--edition=[specify edition to set for the crate generated]:edition:(2015 2018 2021)' \ + '--vcs=[initialize a new repo with a given VCS]:vcs:(git hg pijul fossil none)' \ + '--name=[set the resulting package name]:name' \ + '1:path:_directories' + ;; + + install) + _arguments -s -S $common $parallel $features $triple $registry \ + '(-f --force)'{-f,--force}'[force overwriting of existing crates or binaries]' \ + '--bin=[only install the specified binary]:binary' \ + '--branch=[branch to use when installing from git]:branch' \ + '--debug[Build in debug mode (with the "dev" profile) instead of release mode]' \ + '--example=[install the specified example instead of binaries]:example:_cargo_example_names' \ + '--git=[specify URL from which to install the crate]:url:_urls' \ + '--path=[local filesystem path to crate to install]: :_directories' \ + '--rev=[specific commit to use when installing from git]:commit' \ + '--root=[directory to install packages into]: :_directories' \ + '--tag=[tag to use when installing from git]:tag' \ + '--version=[version to install from crates.io]:version' \ + '--list[list all installed packages and their versions]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' \ + '*: :_guard "^-*" "crate"' + ;; + + locate-project) + _arguments -s -S $common $manifest \ + '--message-format=[specify output representation]:output representation [json]:(json plain)' \ + '--workspace[locate Cargo.toml of the workspace root]' + ;; + + login) + _arguments -s -S $common $registry \ + '*: :_guard "^-*" "token"' + ;; + + metadata) + _arguments -s -S $common $features $manifest \ + "--no-deps[output information only about the root package and don't fetch dependencies]" \ + '--format-version=[specify format version]:version [1]:(1)' + ;; + + new) + _arguments -s -S $common $registry \ + '--lib[use library template]' \ + '--vcs:initialize a new repo with a given VCS:(git hg none)' \ + '--name=[set the resulting package name]' + ;; + + owner) + _arguments -s -S $common $registry \ + '(-a --add)'{-a,--add}'[specify name of a user or team to invite as an owner]:name' \ + '--index=[specify registry index]:index' \ + '(-l --list)'{-l,--list}'[list owners of a crate]' \ + '(-r --remove)'{-r,--remove}'[specify name of a user or team to remove as an owner]:name' \ + '--token=[specify API token to use when authenticating]:token' \ + '*: :_guard "^-*" "crate"' + ;; + + package) + _arguments -s -S $common $parallel $features $triple $target $manifest $registry \ + '--index=[specify registry index]:index' \ + '(-l --list)'{-l,--list}'[print files included in a package without making one]' \ + '--no-metadata[ignore warnings about a lack of human-usable metadata]' \ + '--allow-dirty[allow dirty working directories to be packaged]' \ + "--no-verify[don't build to verify contents]" + ;; + + pkgid) + _arguments -s -S $common $manifest \ + '(-p --package)'{-p+,--package=}'[specify package to get ID specifier for]:package:_cargo_package_names' \ + '*: :_guard "^-*" "spec"' + ;; + + publish) + _arguments -s -S $common $parallel $features $triple $target $manifest $registry \ + '--index=[specify registry index]:index' \ + '--allow-dirty[allow dirty working directories to be packaged]' \ + "--no-verify[don't verify the contents by building them]" \ + '--token=[specify token to use when uploading]:token' \ + '--dry-run[perform all checks without uploading]' + ;; + + remove | rm) + _arguments -s -A "^--" $common $manifest \ + "--dev[remove as a dev dependency]" \ + "--build[remove as a build dependency]" \ + "--target=[remove as a dependency from the given target platform]" \ + "--dry-run[don't actually write the manifest]" \ + '(-p --package)'{-p+,--package=}'[package to remove from]:package:_cargo_package_names' \ + '1: :_guard "^-*" "crate name"' \ + '*:args:_default' + ;; + + run | r) + _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \ + '--example=[name of the bin target]:name:_cargo_example_names' \ + '--bin=[name of the bin target]:name' \ + '(-p --package)'{-p+,--package=}'[specify package with the target to run]:package:_cargo_package_names' \ + '--release[build in release mode]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' \ + '*: :_default' + ;; + + rustc) + _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \ + '(-p --package)'{-p+,--package=}'[specify package to build]:package:_cargo_package_names' \ + '--profile=[specify profile to build the selected target for]:profile' \ + '--release[build artifacts in release mode, with optimizations]' \ + "${command_scope_spec[@]}" \ + '--ignore-rust-version[Ignore rust-version specification in packages]' \ + '*: : _dispatch rustc rustc -default-' + ;; + + rustdoc) + _arguments -s -S $common $parallel $features $msgfmt $triple $target $manifest \ + '--document-private-items[include non-public items in the documentation]' \ + '--open[open the docs in a browser after the operation]' \ + '(-p --package)'{-p+,--package=}'[specify package to document]:package:_cargo_package_names' \ + '--release[build artifacts in release mode, with optimizations]' \ + "${command_scope_spec[@]}" \ + '--ignore-rust-version[Ignore rust-version specification in packages]' \ + '*: : _dispatch rustdoc rustdoc -default-' + ;; + + search) + _arguments -s -S $common $registry \ + '--index=[specify registry index]:index' \ + '--limit=[limit the number of results]:results [10]' \ + '*: :_guard "^-*" "query"' + ;; + + test | t) + _arguments -s -S $common $jobs $features $msgfmt $triple $target $manifest \ + '--test=[test name]: :_cargo_test_names' \ + '--no-fail-fast[run all tests regardless of failure]' \ + '--no-run[compile but do not run]' \ + '(-p --package)'{-p+,--package=}'[package to run tests for]:package:_cargo_package_names' \ + '--all[test all packages in the workspace]' \ + '--release[build artifacts in release mode, with optimizations]' \ + '1: :_cargo_test_names' \ + '(--doc --bin --example --test --bench)--lib[only test library]' \ + '(--lib --bin --example --test --bench)--doc[only test documentation]' \ + '(--lib --doc --example --test --bench)--bin=[binary name]' \ + '(--lib --doc --bin --test --bench)--example=[example name]:_cargo_example_names' \ + '(--lib --doc --bin --example --bench)--test=[test name]' \ + '(--lib --doc --bin --example --test)--bench=[benchmark name]' \ + '--ignore-rust-version[Ignore rust-version specification in packages]' \ + '*: :_default' + ;; + + tree) + _arguments -s -S $common $features $triple $manifest \ + '(-p --package)'{-p+,--package=}'[package to use as the root]:package:_cargo_package_names' \ + '(-i --invert)'{-i+,--invert=}'[invert the tree for the given package]:package:_cargo_package_names' \ + '--prefix=[line prefix]:prefix:(depth indent none)' \ + '--no-dedupe[repeat shared dependencies]' \ + '(-d --duplicates)'{-d,--duplicates}'[packages with multiple versions]' \ + '--charset=[utf8 or ascii]:charset:(utf8 ascii)' \ + '(-f --format)'{-f,--format=}'[format string]:format' \ + '(-e --edges)'{-e,--edges=}'[edge kinds]:kind:(features normal build dev all no-dev no-build no-normal)' \ + ;; + + uninstall) + _arguments -s -S $common \ + '(-p --package)'{-p+,--package=}'[specify package to uninstall]:package:_cargo_package_names' \ + '--bin=[only uninstall the specified binary]:name' \ + '--root=[directory to uninstall packages from]: :_files -/' \ + '*:crate:_cargo_installed_crates -F line' + ;; + + 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' \ + '*:package:_cargo_package_names' + ;; + + version) + _arguments -s -S $common + ;; + + yank) + _arguments -s -S $common $registry \ + '--version=[specify yank version]:version' \ + '--undo[undo a yank, putting a version back into the index]' \ + '--index=[specify registry index to yank from]:registry index' \ + '--token=[specify API token to use when authenticating]:token' \ + '*: :_guard "^-*" "crate"' + ;; + *) + # allow plugins to define their own functions + if ! _call_function ret _cargo-${words[1]}; then + # fallback on default completion for unknown commands + _default && ret=0 + fi + (( ! ret )) + ;; + esac + ;; + esac +} + +_cargo_unstable_flags() { + local flags + flags=( help ${${${(M)${(f)"$(_call_program flags cargo -Z help)"}:#*--*}/ #-- #/:}##*-Z } ) + _describe -t flags 'unstable flag' flags +} + +_cargo_installed_crates() { + local expl + _description crates expl 'crate' + compadd "$@" "$expl[@]" - ${${${(f)"$(cargo install --list)"}:# *}%% *} +} + +_cargo_cmds() { + local -a commands + # This uses Parameter Expansion Flags, which are a built-in Zsh feature. + # See more: http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion-Flags + # and http://zsh.sourceforge.net/Doc/Release/Expansion.html#Parameter-Expansion + # + # # How this work? + # + # First it splits the result of `cargo --list` at newline, then it removes the first line. + # Then it removes indentation (4 whitespaces) before each items. (Note the x## pattern [1]). + # Then it replaces those spaces between item and description with a `:` + # + # [1]: https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org#patterns + commands=( ${${${(M)"${(f)$(_call_program commands cargo --list)}":# *}/ ##/}/ ##/:} ) + _describe -t commands 'command' commands +} + +_cargo_target_triple() { + 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 +#gets package names from the manifest file +_cargo_package_names() { + _message -e packages package +} + +# Extracts the values of "name" from the array given in $1 and shows them as +# command line options for completion +_cargo_names_from_array() { + local manifest=$(cargo locate-project --message-format plain) + if [[ -z $manifest ]]; then + return 0 + fi + + local last_line + local -a names; + local in_block=false + local block_name=$1 + names=() + while read -r line; do + if [[ $last_line == "[[$block_name]]" ]]; then + in_block=true + else + if [[ $last_line =~ '\s*\[\[.*' ]]; then + in_block=false + fi + fi + + if [[ $in_block == true ]]; then + if [[ $line =~ '\s*name\s*=' ]]; then + regexp-replace line '^\s*name\s*=\s*|"' '' + names+=( "$line" ) + fi + fi + + last_line=$line + done < "$manifest" + _describe "$block_name" names + +} + +#Gets the test names from the manifest file +_cargo_test_names() { + _cargo_names_from_array "test" +} + +#Gets the bench names from the manifest file +_cargo_benchmark_names() { + _cargo_names_from_array "bench" +} + +_cargo_example_names() { + if [[ -d examples ]]; then + local -a files=(${(@f)$(echo examples/*.rs(:t:r))}) + _values 'example' "${files[@]}" + fi +} + +_cargo diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/cargo.bashcomp.sh b/collector/compile-benchmarks/cargo-0.87.1/src/etc/cargo.bashcomp.sh new file mode 100644 index 000000000..2a676325d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/cargo.bashcomp.sh @@ -0,0 +1,283 @@ +# Required for bash versions < 4.1 +# Default bash version is 3.2 on latest macOS. See #6874 +shopt -s extglob + +command -v cargo >/dev/null 2>&1 && +_cargo() +{ + local cur prev words cword + _get_comp_words_by_ref cur prev words cword + + COMPREPLY=() + + # Skip past - and + options to find the command. + local nwords=${#words[@]} + local cmd_i cmd dd_i + for (( cmd_i=1; cmd_i<$nwords; cmd_i++ )); + do + if [[ ! "${words[$cmd_i]}" =~ ^[+-] ]]; then + cmd="${words[$cmd_i]}" + break + fi + done + # Find the location of the -- separator. + for (( dd_i=1; dd_i<$nwords-1; dd_i++ )); + do + if [[ "${words[$dd_i]}" = "--" ]]; then + break + fi + done + + local vcs='git hg none pijul fossil' + local color='auto always never' + local msg_format='human json short' + + local opt_help='-h --help' + local opt_verbose='-v --verbose' + local opt_quiet='-q --quiet' + local opt_color='--color' + local opt_common="$opt_help $opt_verbose $opt_quiet $opt_color" + local opt_pkg_spec='-p --package --all --exclude --workspace' + local opt_pkg='-p --package' + local opt_feat='-F --features --all-features --no-default-features' + local opt_mani='--manifest-path' + local opt_jobs='-j --jobs' + local opt_parallel="$opt_jobs --keep-going" + local opt_force='-f --force' + local opt_sync='-s --sync' + local opt_lock='--frozen --locked --offline' + local opt_targets="--lib --bin --bins --example --examples --test --tests --bench --benches --all-targets" + + local opt___nocmd="$opt_common -V --version --list --explain" + local opt__add="$opt_common -p --package --features --default-features --no-default-features $opt_mani --optional --no-optional --rename --dry-run --path --git --branch --tag --rev --registry --dev --build --target --ignore-rust-version" + local opt__bench="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_targets --message-format --target --no-run --no-fail-fast --target-dir --ignore-rust-version" + local opt__build="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --ignore-rust-version" + local opt__b="$opt__build" + local opt__check="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --ignore-rust-version" + local opt__c="$opt__check" + local opt__clean="$opt_common $opt_pkg $opt_mani $opt_lock --target --release --doc --target-dir --profile" + local opt__clippy="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --profile --target-dir --no-deps --fix" + local opt__doc="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_parallel --message-format --bin --bins --lib --target --open --no-deps --release --document-private-items --target-dir --profile --ignore-rust-version" + local opt__d="$opt__doc" + local opt__fetch="$opt_common $opt_mani $opt_lock --target" + local opt__fix="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_parallel $opt_targets $opt_lock --release --target --message-format --broken-code --edition --edition-idioms --allow-no-vcs --allow-dirty --allow-staged --profile --target-dir --ignore-rust-version" + local opt__generate_lockfile="$opt_common $opt_mani $opt_lock" + local opt__help="$opt_help" + local opt__info="$opt_common $opt_lock --registry --index" + local opt__init="$opt_common $opt_lock --bin --lib --name --vcs --edition --registry" + local opt__install="$opt_common $opt_feat $opt_parallel $opt_lock $opt_force --bin --bins --branch --debug --example --examples --git --list --path --rev --root --tag --version --registry --target --profile --no-track --ignore-rust-version" + local opt__locate_project="$opt_common $opt_mani $opt_lock --message-format --workspace" + local opt__login="$opt_common $opt_lock --registry" + local opt__metadata="$opt_common $opt_feat $opt_mani $opt_lock --format-version=1 --no-deps --filter-platform" + local opt__new="$opt_common $opt_lock --vcs --bin --lib --name --edition --registry" + local opt__owner="$opt_common $opt_lock -a --add -r --remove -l --list --index --token --registry" + local opt__package="$opt_common $opt_mani $opt_feat $opt_lock $opt_parallel --allow-dirty -l --list --no-verify --no-metadata --index --registry --target --target-dir" + local opt__pkgid="$opt_common $opt_mani $opt_lock $opt_pkg" + local opt__publish="$opt_common $opt_mani $opt_feat $opt_lock $opt_parallel --allow-dirty --dry-run --token --no-verify --index --registry --target --target-dir" + local opt__remove="$opt_common $opt_pkg $opt_lock $opt_mani --dry-run --dev --build --target" + local opt__rm="$opt__remove" + local opt__report="$opt_help $opt_verbose $opt_color future-incompat future-incompatibilities" + local opt__report__future_incompat="$opt_help $opt_verbose $opt_color $opt_pkg --id" + local opt__run="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel --message-format --target --bin --example --release --target-dir --profile --ignore-rust-version" + local opt__r="$opt__run" + local opt__rustc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets -L --crate-type --extern --message-format --profile --target --release --target-dir --ignore-rust-version" + local opt__rustdoc="$opt_common $opt_pkg $opt_feat $opt_mani $opt_lock $opt_parallel $opt_targets --message-format --target --release --open --target-dir --profile --ignore-rust-version" + local opt__search="$opt_common $opt_lock --limit --index --registry" + local opt__test="$opt_common $opt_pkg_spec $opt_feat $opt_mani $opt_lock $opt_jobs $opt_targets --message-format --doc --target --no-run --release --no-fail-fast --target-dir --profile --ignore-rust-version" + 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 --recursive --precise --dry-run" + local opt__vendor="$opt_common $opt_mani $opt_lock $opt_sync --no-delete --respect-source-config --versioned-dirs" + local opt__version="$opt_common $opt_lock" + local opt__yank="$opt_common $opt_lock --version --undo --index --token --registry" + local opt__libtest="--help --include-ignored --ignored --test --bench --list --logfile --nocapture --test-threads --skip -q --quiet --exact --color --format" + + if [[ $cword -gt $dd_i ]]; then + # Completion after -- separator. + if [[ "${cmd}" = @(test|bench) ]]; then + COMPREPLY=( $( compgen -W "${opt__libtest}" -- "$cur" ) ) + else + # Fallback to filename completion, useful with `cargo run`. + _filedir + fi + elif [[ $cword -le $cmd_i ]]; then + # Completion before or at the command. + if [[ "$cur" == -* ]]; then + COMPREPLY=( $( compgen -W "${opt___nocmd}" -- "$cur" ) ) + elif [[ "$cur" == +* ]]; then + COMPREPLY=( $( compgen -W "$(_toolchains)" -- "$cur" ) ) + else + _ensure_cargo_commands_cache_filled + COMPREPLY=( $( compgen -W "$__cargo_commands_cache" -- "$cur" ) ) + fi + else + case "${prev}" in + --vcs) + COMPREPLY=( $( compgen -W "$vcs" -- "$cur" ) ) + ;; + --color) + COMPREPLY=( $( compgen -W "$color" -- "$cur" ) ) + ;; + --message-format) + COMPREPLY=( $( compgen -W "$msg_format" -- "$cur" ) ) + ;; + --manifest-path) + _filedir toml + ;; + --bin) + COMPREPLY=( $( compgen -W "$(_bin_names)" -- "$cur" ) ) + ;; + --test) + COMPREPLY=( $( compgen -W "$(_test_names)" -- "$cur" ) ) + ;; + --bench) + COMPREPLY=( $( compgen -W "$(_benchmark_names)" -- "$cur" ) ) + ;; + --example) + COMPREPLY=( $( compgen -W "$(_get_examples)" -- "$cur" ) ) + ;; + --target) + COMPREPLY=( $( compgen -W "$(_get_targets)" -- "$cur" ) ) + ;; + --target-dir|--path) + _filedir -d + ;; + help) + _ensure_cargo_commands_cache_filled + COMPREPLY=( $( compgen -W "$__cargo_commands_cache" -- "$cur" ) ) + ;; + *) + if [[ "$cmd" == "report" && "$prev" == future-incompat* ]]; then + local opt_var=opt__${cmd//-/_}__${prev//-/_} + else + local opt_var=opt__${cmd//-/_} + fi + if [[ -z "${!opt_var-}" ]]; then + # Fallback to filename completion. + _filedir + else + COMPREPLY=( $( compgen -W "${!opt_var}" -- "$cur" ) ) + fi + ;; + esac + fi + + # compopt does not work in bash version 3 + + return 0 +} && +complete -F _cargo cargo + +__cargo_commands_cache= +_ensure_cargo_commands_cache_filled(){ + if [[ -z $__cargo_commands_cache ]]; then + __cargo_commands_cache="$(cargo --list 2>/dev/null | awk 'NR>1 {print $1}')" + fi +} + +_locate_manifest(){ + cargo locate-project --message-format plain 2>/dev/null +} + +# Extracts the values of "name" from the array given in $1 and shows them as +# command line options for completion +_get_names_from_array() +{ + local manifest=$(_locate_manifest) + if [[ -z $manifest ]]; then + return 0 + fi + + local last_line + local -a names + local in_block=false + local block_name=$1 + while read line + do + if [[ $last_line == "[[$block_name]]" ]]; then + in_block=true + else + if [[ $last_line =~ .*\[\[.* ]]; then + in_block=false + fi + fi + + if [[ $in_block == true ]]; then + if [[ $line =~ .*name.*\= ]]; then + line=${line##*=} + line=${line%%\"} + line=${line##*\"} + names+=("$line") + fi + fi + + last_line=$line + done < "$manifest" + echo "${names[@]}" +} + +#Gets the bin names from the manifest file +_bin_names() +{ + _get_names_from_array "bin" +} + +#Gets the test names from the manifest file +_test_names() +{ + _get_names_from_array "test" +} + +#Gets the bench names from the manifest file +_benchmark_names() +{ + _get_names_from_array "bench" +} + +_get_examples(){ + local manifest=$(_locate_manifest) + [ -z "$manifest" ] && return 0 + + local files=("${manifest%/*}"/examples/*.rs) + local names=("${files[@]##*/}") + local names=("${names[@]%.*}") + # "*" means no examples found + if [[ "${names[@]}" != "*" ]]; then + echo "${names[@]}" + fi +} + +_get_targets(){ + if command -v rustup >/dev/null 2>/dev/null; then + rustup target list --installed + else + rustc --print target-list + fi +} + +_toolchains(){ + local result=() + local toolchains=$(rustup toolchain list) + local channels="nightly|beta|stable|[0-9]\.[0-9]{1,2}\.[0-9]" + local date="[0-9]{4}-[0-9]{2}-[0-9]{2}" + while read line + do + # Strip " (default)" + line=${line%% *} + if [[ "$line" =~ ^($channels)(-($date))?(-.*) ]]; then + if [[ -z ${BASH_REMATCH[3]} ]]; then + result+=("+${BASH_REMATCH[1]}") + else + # channel-date + result+=("+${BASH_REMATCH[1]}-${BASH_REMATCH[3]}") + fi + result+=("+$line") + else + result+=("+$line") + fi + done <<< "$toolchains" + echo "${result[@]}" +} + +# vim:ft=sh diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-add.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-add.1 new file mode 100644 index 000000000..680642df7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-add.1 @@ -0,0 +1,383 @@ +'\" t +.TH "CARGO\-ADD" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-add \[em] Add dependencies to a Cargo.toml manifest file +.SH "SYNOPSIS" +\fBcargo add\fR [\fIoptions\fR] \fIcrate\fR\[u2026] +.br +\fBcargo add\fR [\fIoptions\fR] \fB\-\-path\fR \fIpath\fR +.br +\fBcargo add\fR [\fIoptions\fR] \fB\-\-git\fR \fIurl\fR [\fIcrate\fR\[u2026]] +.SH "DESCRIPTION" +This command can add or modify dependencies. +.sp +The source for the dependency can be specified with: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fIcrate\fR\fB@\fR\fIversion\fR: Fetch from a registry with a version constraint of \[lq]\fIversion\fR\[rq] +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB\-\-path\fR \fIpath\fR: Fetch from the specified \fIpath\fR +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB\-\-git\fR \fIurl\fR: Pull from a git repo at \fIurl\fR +.RE +.sp +If no source is specified, then a best effort will be made to select one, including: +.sp +.RS 4 +\h'-04'\(bu\h'+03'Existing dependencies in other tables (like \fBdev\-dependencies\fR) +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Workspace members +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Latest release in the registry +.RE +.sp +When you add a package that is already present, the existing entry will be updated with the flags specified. +.sp +Upon successful invocation, the enabled (\fB+\fR) and disabled (\fB\-\fR) \fIfeatures\fR of the specified +dependency will be listed in the command\[cq]s output. +.SH "OPTIONS" +.SS "Source options" +.sp +\fB\-\-git\fR \fIurl\fR +.RS 4 +\fIGit URL to add the specified crate from\fR \&. +.RE +.sp +\fB\-\-branch\fR \fIbranch\fR +.RS 4 +Branch to use when adding from git. +.RE +.sp +\fB\-\-tag\fR \fItag\fR +.RS 4 +Tag to use when adding from git. +.RE +.sp +\fB\-\-rev\fR \fIsha\fR +.RS 4 +Specific commit to use when adding from git. +.RE +.sp +\fB\-\-path\fR \fIpath\fR +.RS 4 +\fIFilesystem path\fR to local crate to add. +.RE +.sp +\fB\-\-base\fR \fIbase\fR +.RS 4 +The \fIpath base\fR to use when adding a local crate. +.sp +\fIUnstable (nightly\-only)\fR +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.SS "Section options" +.sp +\fB\-\-dev\fR +.RS 4 +Add as a \fIdevelopment dependency\fR \&. +.RE +.sp +\fB\-\-build\fR +.RS 4 +Add as a \fIbuild dependency\fR \&. +.RE +.sp +\fB\-\-target\fR \fItarget\fR +.RS 4 +Add as a dependency to the \fIgiven target platform\fR \&. +.sp +To avoid unexpected shell expansions, you may use quotes around each target, e.g., \fB\-\-target 'cfg(unix)'\fR\&. +.RE +.SS "Dependency options" +.sp +\fB\-\-dry\-run\fR +.RS 4 +Don\[cq]t actually write the manifest +.RE +.sp +\fB\-\-rename\fR \fIname\fR +.RS 4 +\fIRename\fR the dependency. +.RE +.sp +\fB\-\-optional\fR +.RS 4 +Mark the dependency as \fIoptional\fR \&. +.RE +.sp +\fB\-\-no\-optional\fR +.RS 4 +Mark the dependency as \fIrequired\fR \&. +.RE +.sp +\fB\-\-public\fR +.RS 4 +Mark the dependency as public. +.sp +The dependency can be referenced in your library\[cq]s public API. +.sp +\fIUnstable (nightly\-only)\fR +.RE +.sp +\fB\-\-no\-public\fR +.RS 4 +Mark the dependency as private. +.sp +While you can use the crate in your implementation, it cannot be referenced in your public API. +.sp +\fIUnstable (nightly\-only)\fR +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Disable the \fIdefault features\fR \&. +.RE +.sp +\fB\-\-default\-features\fR +.RS 4 +Re\-enable the \fIdefault features\fR \&. +.RE +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of \fIfeatures to +activate\fR \&. When adding multiple +crates, the features for a specific crate may be enabled with +\fBpackage\-name/feature\-name\fR syntax. This flag may be specified multiple times, +which enables all specified features. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-p\fR \fIspec\fR, +\fB\-\-package\fR \fIspec\fR +.RS 4 +Add dependencies to only the specified package. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Add \fBregex\fR as a dependency +.sp +.RS 4 +.nf +cargo add regex +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Add \fBtrybuild\fR as a dev\-dependency +.sp +.RS 4 +.nf +cargo add \-\-dev trybuild +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Add an older version of \fBnom\fR as a dependency +.sp +.RS 4 +.nf +cargo add nom@5 +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 4.\h'+01'Add support for serializing data structures to json with \fBderive\fRs +.sp +.RS 4 +.nf +cargo add serde serde_json \-F serde/derive +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 5.\h'+01'Add \fBwindows\fR as a platform specific dependency on \fBcfg(windows)\fR +.sp +.RS 4 +.nf +cargo add windows \-\-target 'cfg(windows)' +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-remove\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-bench.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-bench.1 new file mode 100644 index 000000000..f28ddb307 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-bench.1 @@ -0,0 +1,573 @@ +'\" t +.TH "CARGO\-BENCH" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-bench \[em] Execute benchmarks of a package +.SH "SYNOPSIS" +\fBcargo bench\fR [\fIoptions\fR] [\fIbenchname\fR] [\fB\-\-\fR \fIbench\-options\fR] +.SH "DESCRIPTION" +Compile and execute benchmarks. +.sp +The benchmark filtering argument \fIbenchname\fR and all the arguments following +the two dashes (\fB\-\-\fR) are passed to the benchmark binaries and thus to +\fIlibtest\fR (rustc\[cq]s built in unit\-test and micro\-benchmarking framework). If +you are passing arguments to both Cargo and the binary, the ones after \fB\-\-\fR go +to the binary, the ones before go to Cargo. For details about libtest\[cq]s +arguments see the output of \fBcargo bench \-\- \-\-help\fR and check out the rustc +book\[cq]s chapter on how tests work at +\&. +.sp +As an example, this will run only the benchmark named \fBfoo\fR (and skip other +similarly named benchmarks like \fBfoobar\fR): +.sp +.RS 4 +.nf +cargo bench \-\- foo \-\-exact +.fi +.RE +.sp +Benchmarks are built with the \fB\-\-test\fR option to \fBrustc\fR which creates a +special executable by linking your code with libtest. The executable +automatically runs all functions annotated with the \fB#[bench]\fR attribute. +Cargo passes the \fB\-\-bench\fR flag to the test harness to tell it to run +only benchmarks, regardless of whether the harness is libtest or a custom harness. +.sp +The libtest harness may be disabled by setting \fBharness = false\fR in the target +manifest settings, in which case your code will need to provide its own \fBmain\fR +function to handle running benchmarks. +.RS 3 +.ll -5 +.sp +\fBNote\fR: The +\fI\f(BI#[bench]\fI attribute\fR +is currently unstable and only available on the +\fInightly channel\fR \&. +There are some packages available on +\fIcrates.io\fR that may help with +running benchmarks on the stable channel, such as +\fICriterion\fR \&. +.br +.RE +.ll +.sp +By default, \fBcargo bench\fR uses the \fI\f(BIbench\fI profile\fR , which enables +optimizations and disables debugging information. If you need to debug a +benchmark, you can use the \fB\-\-profile=dev\fR command\-line option to switch to +the dev profile. You can then run the debug\-enabled benchmark within a +debugger. +.SS "Working directory of benchmarks" +The working directory of every benchmark is set to the root directory of the +package the benchmark belongs to. +Setting the working directory of benchmarks to the package\[cq]s root directory +makes it possible for benchmarks to reliably access the package\[cq]s files using +relative paths, regardless from where \fBcargo bench\fR was executed from. +.SH "OPTIONS" +.SS "Benchmark Options" +.sp +\fB\-\-no\-run\fR +.RS 4 +Compile, but don\[cq]t run benchmarks. +.RE +.sp +\fB\-\-no\-fail\-fast\fR +.RS 4 +Run all benchmarks regardless of failure. Without this flag, Cargo will exit +after the first executable fails. The Rust test harness will run all benchmarks +within the executable to completion, this flag only applies to the executable +as a whole. +.RE +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Benchmark only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Benchmark all members in the workspace. +.RE +.sp +\fB\-\-all\fR +.RS 4 +Deprecated alias for \fB\-\-workspace\fR\&. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo bench\fR will build the +following targets of the selected packages: +.sp +.RS 4 +\h'-04'\(bu\h'+03'lib \[em] used to link with binaries and benchmarks +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'bins (only if benchmark targets are built and required features are +available) +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'lib as a benchmark +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'bins as benchmarks +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'benchmark targets +.RE +.sp +The default behavior can be changed by setting the \fBbench\fR flag for the target +in the manifest settings. Setting examples to \fBbench = true\fR will build and +run the example as a benchmark, replacing the example\[cq]s \fBmain\fR function with +the libtest harness. +.sp +Setting targets to \fBbench = false\fR will stop them from being benchmarked by +default. Target selection options that take a target by name (such as +\fB\-\-example foo\fR) ignore the \fBbench\fR flag and will always benchmark the given +target. +.sp +See \fIConfiguring a target\fR +for more information on per\-target settings. +.sp +Binary targets are automatically built if there is an integration test or +benchmark being selected to benchmark. This allows an integration +test to execute the binary to exercise and test its behavior. +The \fBCARGO_BIN_EXE_\fR +\fIenvironment variable\fR +is set when the integration test is built so that it can use the +\fI\f(BIenv\fI macro\fR to locate the +executable. +.sp +Passing target selection flags will benchmark only the specified +targets. +.sp +Note that \fB\-\-bin\fR, \fB\-\-example\fR, \fB\-\-test\fR and \fB\-\-bench\fR flags also +support common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your +shell accidentally expanding glob patterns before Cargo handles them, you must +use single quotes or double quotes around each glob pattern. +.sp +\fB\-\-lib\fR +.RS 4 +Benchmark the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Benchmark the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Benchmark all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Benchmark the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Benchmark all example targets. +.RE +.sp +\fB\-\-test\fR \fIname\fR\[u2026] +.RS 4 +Benchmark the specified integration test. This flag may be specified +multiple times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-tests\fR +.RS 4 +Benchmark all targets that have the \fBtest = true\fR manifest +flag set. By default this includes the library and binaries built as +unittests, and integration tests. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +unittest, and once as a dependency for binaries, integration tests, etc.). +Targets may be enabled or disabled by setting the \fBtest\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-bench\fR \fIname\fR\[u2026] +.RS 4 +Benchmark the specified benchmark. This flag may be specified multiple +times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-benches\fR +.RS 4 +Benchmark all targets that have the \fBbench = true\fR +manifest flag set. By default this includes the library and binaries built +as benchmarks, and bench targets. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +benchmark, and once as a dependency for binaries, benchmarks, etc.). +Targets may be enabled or disabled by setting the \fBbench\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-all\-targets\fR +.RS 4 +Benchmark all targets. This is equivalent to specifying \fB\-\-lib \-\-bins \-\-tests \-\-benches \-\-examples\fR\&. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Benchmark for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Benchmark with the given profile. +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +By default the Rust test harness hides output from benchmark execution to keep +results readable. Benchmark output can be recovered (e.g., for debugging) by +passing \fB\-\-nocapture\fR to the benchmark binaries: +.sp +.RS 4 +.nf +cargo bench \-\- \-\-nocapture +.fi +.RE +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +The \fB\-\-jobs\fR argument affects the building of the benchmark executable but +does not affect how many threads are used when running the benchmarks. The +Rust test harness runs benchmarks serially in a single thread. +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +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 +.nf +cargo build \-\-benches \-\-release \-\-keep\-going +cargo bench \-\-no\-fail\-fast +.fi +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Build and execute all the benchmarks of the current package: +.sp +.RS 4 +.nf +cargo bench +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Run only a specific benchmark within a specific benchmark target: +.sp +.RS 4 +.nf +cargo bench \-\-bench bench_name \-\- modname::some_benchmark +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-test\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-build.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-build.1 new file mode 100644 index 000000000..cf8ab4e50 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-build.1 @@ -0,0 +1,496 @@ +'\" t +.TH "CARGO\-BUILD" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-build \[em] Compile the current package +.SH "SYNOPSIS" +\fBcargo build\fR [\fIoptions\fR] +.SH "DESCRIPTION" +Compile local packages and all of their dependencies. +.SH "OPTIONS" +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Build only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Build all members in the workspace. +.RE +.sp +\fB\-\-all\fR +.RS 4 +Deprecated alias for \fB\-\-workspace\fR\&. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo build\fR will build all +binary and library targets of the selected packages. Binaries are skipped if +they have \fBrequired\-features\fR that are missing. +.sp +Binary targets are automatically built if there is an integration test or +benchmark being selected to build. This allows an integration +test to execute the binary to exercise and test its behavior. +The \fBCARGO_BIN_EXE_\fR +\fIenvironment variable\fR +is set when the integration test is built so that it can use the +\fI\f(BIenv\fI macro\fR to locate the +executable. +.sp +Passing target selection flags will build only the specified +targets. +.sp +Note that \fB\-\-bin\fR, \fB\-\-example\fR, \fB\-\-test\fR and \fB\-\-bench\fR flags also +support common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your +shell accidentally expanding glob patterns before Cargo handles them, you must +use single quotes or double quotes around each glob pattern. +.sp +\fB\-\-lib\fR +.RS 4 +Build the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Build the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Build all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Build the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Build all example targets. +.RE +.sp +\fB\-\-test\fR \fIname\fR\[u2026] +.RS 4 +Build the specified integration test. This flag may be specified +multiple times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-tests\fR +.RS 4 +Build all targets that have the \fBtest = true\fR manifest +flag set. By default this includes the library and binaries built as +unittests, and integration tests. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +unittest, and once as a dependency for binaries, integration tests, etc.). +Targets may be enabled or disabled by setting the \fBtest\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-bench\fR \fIname\fR\[u2026] +.RS 4 +Build the specified benchmark. This flag may be specified multiple +times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-benches\fR +.RS 4 +Build all targets that have the \fBbench = true\fR +manifest flag set. By default this includes the library and binaries built +as benchmarks, and bench targets. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +benchmark, and once as a dependency for binaries, benchmarks, etc.). +Targets may be enabled or disabled by setting the \fBbench\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-all\-targets\fR +.RS 4 +Build all targets. This is equivalent to specifying \fB\-\-lib \-\-bins \-\-tests \-\-benches \-\-examples\fR\&. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Build for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Build optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Build with the given profile. +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.sp +\fB\-\-artifact\-dir\fR \fIdirectory\fR +.RS 4 +Copy final artifacts to this directory. +.sp +This option is unstable and available only on the +\fInightly channel\fR +and requires the \fB\-Z unstable\-options\fR flag to enable. +See for more information. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.sp +\fB\-\-build\-plan\fR +.RS 4 +Outputs a series of JSON messages to stdout that indicate the commands to run +the build. +.sp +This option is unstable and available only on the +\fInightly channel\fR +and requires the \fB\-Z unstable\-options\fR flag to enable. +See for more information. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 +.RS 4 +Displays a future\-incompat report for any future\-incompatible warnings +produced during execution of this command +.sp +See \fBcargo\-report\fR(1) +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Build the local package and all of its dependencies: +.sp +.RS 4 +.nf +cargo build +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Build with optimizations: +.sp +.RS 4 +.nf +cargo build \-\-release +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-rustc\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-check.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-check.1 new file mode 100644 index 000000000..2805c2b59 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-check.1 @@ -0,0 +1,477 @@ +'\" t +.TH "CARGO\-CHECK" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-check \[em] Check the current package +.SH "SYNOPSIS" +\fBcargo check\fR [\fIoptions\fR] +.SH "DESCRIPTION" +Check a local package and all of its dependencies for errors. This will +essentially compile the packages without performing the final step of code +generation, which is faster than running \fBcargo build\fR\&. The compiler will save +metadata files to disk so that future runs will reuse them if the source has +not been modified. Some diagnostics and errors are only emitted during code +generation, so they inherently won\[cq]t be reported with \fBcargo check\fR\&. +.SH "OPTIONS" +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Check only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Check all members in the workspace. +.RE +.sp +\fB\-\-all\fR +.RS 4 +Deprecated alias for \fB\-\-workspace\fR\&. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo check\fR will check all +binary and library targets of the selected packages. Binaries are skipped if +they have \fBrequired\-features\fR that are missing. +.sp +Passing target selection flags will check only the specified +targets. +.sp +Note that \fB\-\-bin\fR, \fB\-\-example\fR, \fB\-\-test\fR and \fB\-\-bench\fR flags also +support common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your +shell accidentally expanding glob patterns before Cargo handles them, you must +use single quotes or double quotes around each glob pattern. +.sp +\fB\-\-lib\fR +.RS 4 +Check the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Check the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Check all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Check the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Check all example targets. +.RE +.sp +\fB\-\-test\fR \fIname\fR\[u2026] +.RS 4 +Check the specified integration test. This flag may be specified +multiple times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-tests\fR +.RS 4 +Check all targets that have the \fBtest = true\fR manifest +flag set. By default this includes the library and binaries built as +unittests, and integration tests. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +unittest, and once as a dependency for binaries, integration tests, etc.). +Targets may be enabled or disabled by setting the \fBtest\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-bench\fR \fIname\fR\[u2026] +.RS 4 +Check the specified benchmark. This flag may be specified multiple +times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-benches\fR +.RS 4 +Check all targets that have the \fBbench = true\fR +manifest flag set. By default this includes the library and binaries built +as benchmarks, and bench targets. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +benchmark, and once as a dependency for binaries, benchmarks, etc.). +Targets may be enabled or disabled by setting the \fBbench\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-all\-targets\fR +.RS 4 +Check all targets. This is equivalent to specifying \fB\-\-lib \-\-bins \-\-tests \-\-benches \-\-examples\fR\&. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Check for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Check optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Check with the given profile. +.sp +As a special case, specifying the \fBtest\fR profile will also enable checking in +test mode which will enable checking tests and enable the \fBtest\fR cfg option. +See \fIrustc tests\fR for more +detail. +.sp +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 +.RS 4 +Displays a future\-incompat report for any future\-incompatible warnings +produced during execution of this command +.sp +See \fBcargo\-report\fR(1) +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Check the local package for errors: +.sp +.RS 4 +.nf +cargo check +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Check all targets, including unit tests: +.sp +.RS 4 +.nf +cargo check \-\-all\-targets \-\-profile=test +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-build\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-clean.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-clean.1 new file mode 100644 index 000000000..c3cb9f2bc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-clean.1 @@ -0,0 +1,245 @@ +'\" t +.TH "CARGO\-CLEAN" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-clean \[em] Remove generated artifacts +.SH "SYNOPSIS" +\fBcargo clean\fR [\fIoptions\fR] +.SH "DESCRIPTION" +Remove artifacts from the target directory that Cargo has generated in the +past. +.sp +With no options, \fBcargo clean\fR will delete the entire target directory. +.SH "OPTIONS" +.SS "Package Selection" +When no packages are selected, all packages and all dependencies in the +workspace are cleaned. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Clean only the specified packages. This flag may be specified +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 +the target directory. +.RE +.sp +\fB\-\-release\fR +.RS 4 +Remove all artifacts in the \fBrelease\fR directory. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Remove all artifacts in the directory with the given profile name. +.RE +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Clean for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Remove the entire target directory: +.sp +.RS 4 +.nf +cargo clean +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Remove only the release artifacts: +.sp +.RS 4 +.nf +cargo clean \-\-release +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-build\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-doc.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-doc.1 new file mode 100644 index 000000000..b236f12a8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-doc.1 @@ -0,0 +1,427 @@ +'\" t +.TH "CARGO\-DOC" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-doc \[em] Build a package\[cq]s documentation +.SH "SYNOPSIS" +\fBcargo doc\fR [\fIoptions\fR] +.SH "DESCRIPTION" +Build the documentation for the local package and all dependencies. The output +is placed in \fBtarget/doc\fR in rustdoc\[cq]s usual format. +.SH "OPTIONS" +.SS "Documentation Options" +.sp +\fB\-\-open\fR +.RS 4 +Open the docs in a browser after building them. This will use your default +browser unless you define another one in the \fBBROWSER\fR environment variable +or use the \fI\f(BIdoc.browser\fI\fR configuration +option. +.RE +.sp +\fB\-\-no\-deps\fR +.RS 4 +Do not build documentation for dependencies. +.RE +.sp +\fB\-\-document\-private\-items\fR +.RS 4 +Include non\-public items in the documentation. This will be enabled by default if documenting a binary target. +.RE +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Document only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Document all members in the workspace. +.RE +.sp +\fB\-\-all\fR +.RS 4 +Deprecated alias for \fB\-\-workspace\fR\&. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo doc\fR will document all +binary and library targets of the selected package. The binary will be skipped +if its name is the same as the lib target. Binaries are skipped if they have +\fBrequired\-features\fR that are missing. +.sp +The default behavior can be changed by setting \fBdoc = false\fR for the target in +the manifest settings. Using target selection options will ignore the \fBdoc\fR +flag and will always document the given target. +.sp +\fB\-\-lib\fR +.RS 4 +Document the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Document the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Document all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Document the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Document all example targets. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Document for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Document optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Document with the given profile. +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Build the local package documentation and its dependencies and output to +\fBtarget/doc\fR\&. +.sp +.RS 4 +.nf +cargo doc +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-rustdoc\fR(1), \fBrustdoc\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fetch.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fetch.1 new file mode 100644 index 000000000..cb2f7652a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fetch.1 @@ -0,0 +1,201 @@ +'\" t +.TH "CARGO\-FETCH" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-fetch \[em] Fetch dependencies of a package from the network +.SH "SYNOPSIS" +\fBcargo fetch\fR [\fIoptions\fR] +.SH "DESCRIPTION" +If a \fBCargo.lock\fR file is available, this command will ensure that all of the +git dependencies and/or registry dependencies are downloaded and locally +available. Subsequent Cargo commands will be able to run offline after a \fBcargo fetch\fR unless the lock file changes. +.sp +If the lock file is not available, then this command will generate the lock +file before fetching the dependencies. +.sp +If \fB\-\-target\fR is not specified, then all target dependencies are fetched. +.sp +See also the \fIcargo\-prefetch\fR +plugin which adds a command to download popular crates. This may be useful if +you plan to use Cargo without a network with the \fB\-\-offline\fR flag. +.SH "OPTIONS" +.SS "Fetch options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Fetch for the given architecture. The default is all architectures. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Fetch all dependencies: +.sp +.RS 4 +.nf +cargo fetch +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-update\fR(1), \fBcargo\-generate\-lockfile\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fix.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fix.1 new file mode 100644 index 000000000..f44b28fcc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-fix.1 @@ -0,0 +1,574 @@ +'\" t +.TH "CARGO\-FIX" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-fix \[em] Automatically fix lint warnings reported by rustc +.SH "SYNOPSIS" +\fBcargo fix\fR [\fIoptions\fR] +.SH "DESCRIPTION" +This Cargo subcommand will automatically take rustc\[cq]s suggestions from +diagnostics like warnings and apply them to your source code. This is intended +to help automate tasks that rustc itself already knows how to tell you to fix! +.sp +Executing \fBcargo fix\fR will under the hood execute \fBcargo\-check\fR(1). Any warnings +applicable to your crate will be automatically fixed (if possible) and all +remaining warnings will be displayed when the check process is finished. For +example if you\[cq]d like to apply all fixes to the current package, you can run: +.sp +.RS 4 +.nf +cargo fix +.fi +.RE +.sp +which behaves the same as \fBcargo check \-\-all\-targets\fR\&. +.sp +\fBcargo fix\fR is only capable of fixing code that is normally compiled with +\fBcargo check\fR\&. If code is conditionally enabled with optional features, you +will need to enable those features for that code to be analyzed: +.sp +.RS 4 +.nf +cargo fix \-\-features foo +.fi +.RE +.sp +Similarly, other \fBcfg\fR expressions like platform\-specific code will need to +pass \fB\-\-target\fR to fix code for the given target. +.sp +.RS 4 +.nf +cargo fix \-\-target x86_64\-pc\-windows\-gnu +.fi +.RE +.sp +If you encounter any problems with \fBcargo fix\fR or otherwise have any questions +or feature requests please don\[cq]t hesitate to file an issue at +\&. +.SS "Edition migration" +The \fBcargo fix\fR subcommand can also be used to migrate a package from one +\fIedition\fR to the next. The general procedure is: +.sp +.RS 4 +\h'-04' 1.\h'+01'Run \fBcargo fix \-\-edition\fR\&. Consider also using the \fB\-\-all\-features\fR flag if +your project has multiple features. You may also want to run \fBcargo fix \-\-edition\fR multiple times with different \fB\-\-target\fR flags if your project +has platform\-specific code gated by \fBcfg\fR attributes. +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Modify \fBCargo.toml\fR to set the \fIedition field\fR to the new edition. +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Run your project tests to verify that everything still works. If new +warnings are issued, you may want to consider running \fBcargo fix\fR again +(without the \fB\-\-edition\fR flag) to apply any suggestions given by the +compiler. +.RE +.sp +And hopefully that\[cq]s it! Just keep in mind of the caveats mentioned above that +\fBcargo fix\fR cannot update code for inactive features or \fBcfg\fR expressions. +Also, in some rare cases the compiler is unable to automatically migrate all +code to the new edition, and this may require manual changes after building +with the new edition. +.SH "OPTIONS" +.SS "Fix options" +.sp +\fB\-\-broken\-code\fR +.RS 4 +Fix code even if it already has compiler errors. This is useful if \fBcargo fix\fR +fails to apply the changes. It will apply the changes and leave the broken +code in the working directory for you to inspect and manually fix. +.RE +.sp +\fB\-\-edition\fR +.RS 4 +Apply changes that will update the code to the next edition. This will not +update the edition in the \fBCargo.toml\fR manifest, which must be updated +manually after \fBcargo fix \-\-edition\fR has finished. +.RE +.sp +\fB\-\-edition\-idioms\fR +.RS 4 +Apply suggestions that will update code to the preferred style for the current +edition. +.RE +.sp +\fB\-\-allow\-no\-vcs\fR +.RS 4 +Fix code even if a VCS was not detected. +.RE +.sp +\fB\-\-allow\-dirty\fR +.RS 4 +Fix code even if the working directory has changes (including staged changes). +.RE +.sp +\fB\-\-allow\-staged\fR +.RS 4 +Fix code even if the working directory has staged changes. +.RE +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Fix only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Fix all members in the workspace. +.RE +.sp +\fB\-\-all\fR +.RS 4 +Deprecated alias for \fB\-\-workspace\fR\&. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo fix\fR will fix all targets +(\fB\-\-all\-targets\fR implied). Binaries are skipped if they have +\fBrequired\-features\fR that are missing. +.sp +Passing target selection flags will fix only the specified +targets. +.sp +Note that \fB\-\-bin\fR, \fB\-\-example\fR, \fB\-\-test\fR and \fB\-\-bench\fR flags also +support common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your +shell accidentally expanding glob patterns before Cargo handles them, you must +use single quotes or double quotes around each glob pattern. +.sp +\fB\-\-lib\fR +.RS 4 +Fix the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Fix the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Fix all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Fix the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Fix all example targets. +.RE +.sp +\fB\-\-test\fR \fIname\fR\[u2026] +.RS 4 +Fix the specified integration test. This flag may be specified +multiple times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-tests\fR +.RS 4 +Fix all targets that have the \fBtest = true\fR manifest +flag set. By default this includes the library and binaries built as +unittests, and integration tests. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +unittest, and once as a dependency for binaries, integration tests, etc.). +Targets may be enabled or disabled by setting the \fBtest\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-bench\fR \fIname\fR\[u2026] +.RS 4 +Fix the specified benchmark. This flag may be specified multiple +times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-benches\fR +.RS 4 +Fix all targets that have the \fBbench = true\fR +manifest flag set. By default this includes the library and binaries built +as benchmarks, and bench targets. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +benchmark, and once as a dependency for binaries, benchmarks, etc.). +Targets may be enabled or disabled by setting the \fBbench\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-all\-targets\fR +.RS 4 +Fix all targets. This is equivalent to specifying \fB\-\-lib \-\-bins \-\-tests \-\-benches \-\-examples\fR\&. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Fix for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Fix optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Fix with the given profile. +.sp +As a special case, specifying the \fBtest\fR profile will also enable checking in +test mode which will enable checking tests and enable the \fBtest\fR cfg option. +See \fIrustc tests\fR for more +detail. +.sp +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Apply compiler suggestions to the local package: +.sp +.RS 4 +.nf +cargo fix +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Update a package to prepare it for the next edition: +.sp +.RS 4 +.nf +cargo fix \-\-edition +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Apply suggested idioms for the current edition: +.sp +.RS 4 +.nf +cargo fix \-\-edition\-idioms +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-check\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-generate-lockfile.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-generate-lockfile.1 new file mode 100644 index 000000000..7dda7ac64 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-generate-lockfile.1 @@ -0,0 +1,187 @@ +'\" t +.TH "CARGO\-GENERATE\-LOCKFILE" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-generate\-lockfile \[em] Generate the lockfile for a package +.SH "SYNOPSIS" +\fBcargo generate\-lockfile\fR [\fIoptions\fR] +.SH "DESCRIPTION" +This command will create the \fBCargo.lock\fR lockfile for the current package or +workspace. If the lockfile already exists, it will be rebuilt with the latest +available version of every package. +.sp +See also \fBcargo\-update\fR(1) which is also capable of creating a \fBCargo.lock\fR +lockfile and has more options for controlling update behavior. +.SH "OPTIONS" +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Create or update the lockfile for the current package or workspace: +.sp +.RS 4 +.nf +cargo generate\-lockfile +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-update\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-help.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-help.1 new file mode 100644 index 000000000..655328550 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-help.1 @@ -0,0 +1,34 @@ +'\" t +.TH "CARGO\-HELP" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-help \[em] Get help for a Cargo command +.SH "SYNOPSIS" +\fBcargo help\fR [\fIsubcommand\fR] +.SH "DESCRIPTION" +Prints a help message for the given command. +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Get help for a command: +.sp +.RS 4 +.nf +cargo help build +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Help is also available with the \fB\-\-help\fR flag: +.sp +.RS 4 +.nf +cargo build \-\-help +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-info.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-info.1 new file mode 100644 index 000000000..1be7b6946 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-info.1 @@ -0,0 +1,201 @@ +'\" t +.TH "CARGO\-INFO" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-info \[em] Display information about a package. +.SH "SYNOPSIS" +\fBcargo info\fR [\fIoptions\fR] \fIspec\fR +.SH "DESCRIPTION" +This command displays information about a package. It fetches data from the package\[cq]s Cargo.toml file +and presents it in a human\-readable format. +.SH "OPTIONS" +.SS "Info Options" +.sp +\fIspec\fR +.RS 4 +Fetch information about the specified package. The \fIspec\fR can be a package ID, see \fBcargo\-pkgid\fR(1) for the SPEC +format. +If the specified package is part of the current workspace, information from the local Cargo.toml file will be displayed. +If the \fBCargo.lock\fR file does not exist, it will be created. If no version is specified, the appropriate version will be +selected based on the Minimum Supported Rust Version (MSRV). +.RE +.sp +\fB\-\-index\fR \fIindex\fR +.RS 4 +The URL of the registry index to use. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Inspect the \fBserde\fR package from crates.io: +.sp +.RS 4 +.nf + cargo info serde +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Inspect the \fBserde\fR package with version \fB1.0.0\fR: +.sp +.RS 4 +.nf + cargo info serde@1.0.0 +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Inspect the \fBserde\fR package form the local registry: +.sp +.RS 4 +.nf + cargo info serde \-\-registry my\-registry +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-search\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-init.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-init.1 new file mode 100644 index 000000000..abeb9ebb9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-init.1 @@ -0,0 +1,171 @@ +'\" t +.TH "CARGO\-INIT" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-init \[em] Create a new Cargo package in an existing directory +.SH "SYNOPSIS" +\fBcargo init\fR [\fIoptions\fR] [\fIpath\fR] +.SH "DESCRIPTION" +This command will create a new Cargo manifest in the current directory. Give a +path as an argument to create in the given directory. +.sp +If there are typically\-named Rust source files already in the directory, those +will be used. If not, then a sample \fBsrc/main.rs\fR file will be created, or +\fBsrc/lib.rs\fR if \fB\-\-lib\fR is passed. +.sp +If the directory is not already in a VCS repository, then a new repository +is created (see \fB\-\-vcs\fR below). +.sp +See \fBcargo\-new\fR(1) for a similar command which will create a new package in +a new directory. +.SH "OPTIONS" +.SS "Init Options" +.sp +\fB\-\-bin\fR +.RS 4 +Create a package with a binary target (\fBsrc/main.rs\fR). +This is the default behavior. +.RE +.sp +\fB\-\-lib\fR +.RS 4 +Create a package with a library target (\fBsrc/lib.rs\fR). +.RE +.sp +\fB\-\-edition\fR \fIedition\fR +.RS 4 +Specify the Rust edition to use. Default is 2024. +Possible values: 2015, 2018, 2021, 2024 +.RE +.sp +\fB\-\-name\fR \fIname\fR +.RS 4 +Set the package name. Defaults to the directory name. +.RE +.sp +\fB\-\-vcs\fR \fIvcs\fR +.RS 4 +Initialize a new VCS repository for the given version control system (git, +hg, pijul, or fossil) or do not initialize any version control at all +(none). If not specified, defaults to \fBgit\fR or the configuration value +\fBcargo\-new.vcs\fR, or \fBnone\fR if already inside a VCS repository. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +This sets the \fBpublish\fR field in \fBCargo.toml\fR to the given registry name +which will restrict publishing only to that registry. +.sp +Registry names are defined in \fICargo config files\fR \&. +If not specified, the default registry defined by the \fBregistry.default\fR +config key is used. If the default registry is not set and \fB\-\-registry\fR is not +used, the \fBpublish\fR field will not be set which means that publishing will not +be restricted. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Create a binary Cargo package in the current directory: +.sp +.RS 4 +.nf +cargo init +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-new\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-install.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-install.1 new file mode 100644 index 000000000..4b6bc4506 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-install.1 @@ -0,0 +1,536 @@ +'\" t +.TH "CARGO\-INSTALL" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-install \[em] Build and install a Rust binary +.SH "SYNOPSIS" +\fBcargo install\fR [\fIoptions\fR] \fIcrate\fR[@\fIversion\fR]\[u2026] +.br +\fBcargo install\fR [\fIoptions\fR] \fB\-\-path\fR \fIpath\fR +.br +\fBcargo install\fR [\fIoptions\fR] \fB\-\-git\fR \fIurl\fR [\fIcrate\fR\[u2026]] +.br +\fBcargo install\fR [\fIoptions\fR] \fB\-\-list\fR +.SH "DESCRIPTION" +This command manages Cargo\[cq]s local set of installed binary crates. Only +packages which have executable \fB[[bin]]\fR or \fB[[example]]\fR targets can be +installed, and all executables are installed into the installation root\[cq]s +\fBbin\fR folder. By default only binaries, not examples, are installed. +.sp +The installation root is determined, in order of precedence: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB\-\-root\fR option +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBCARGO_INSTALL_ROOT\fR environment variable +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBinstall.root\fR Cargo \fIconfig value\fR +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBCARGO_HOME\fR environment variable +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB$HOME/.cargo\fR +.RE +.sp +There are multiple sources from which a crate can be installed. The default +source location is crates.io but the \fB\-\-git\fR, \fB\-\-path\fR, and \fB\-\-registry\fR flags +can change this source. If the source contains more than one package (such as +crates.io or a git repository with multiple crates) the \fIcrate\fR argument is +required to indicate which crate should be installed. +.sp +Crates from crates.io can optionally specify the version they wish to install +via the \fB\-\-version\fR flags, and similarly packages from git repositories can +optionally specify the branch, tag, or revision that should be installed. If a +crate has multiple binaries, the \fB\-\-bin\fR argument can selectively install only +one of them, and if you\[cq]d rather install examples the \fB\-\-example\fR argument can +be used as well. +.sp +If the package is already installed, Cargo will reinstall it if the installed +version does not appear to be up\-to\-date. If any of the following values +change, then Cargo will reinstall the package: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The package version and source. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'The set of binary names installed. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'The chosen features. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'The profile (\fB\-\-profile\fR). +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'The target (\fB\-\-target\fR). +.RE +.sp +Installing with \fB\-\-path\fR will always build and install, unless there are +conflicting binaries from another package. The \fB\-\-force\fR flag may be used to +force Cargo to always reinstall the package. +.sp +If the source is crates.io or \fB\-\-git\fR then by default the crate will be built +in a temporary target directory. To avoid this, the target directory can be +specified by setting the \fBCARGO_TARGET_DIR\fR environment variable to a relative +path. In particular, this can be useful for caching build artifacts on +continuous integration systems. +.SS "Dealing with the Lockfile" +By default, the \fBCargo.lock\fR file that is included with the package will be +ignored. This means that Cargo will recompute which versions of dependencies +to use, possibly using newer versions that have been released since the +package was published. The \fB\-\-locked\fR flag can be used to force Cargo to use +the packaged \fBCargo.lock\fR file if it is available. This may be useful for +ensuring reproducible builds, to use the exact same set of dependencies that +were available when the package was published. It may also be useful if a +newer version of a dependency is published that no longer builds on your +system, or has other problems. The downside to using \fB\-\-locked\fR is that you +will not receive any fixes or updates to any dependency. Note that Cargo did +not start publishing \fBCargo.lock\fR files until version 1.37, which means +packages published with prior versions will not have a \fBCargo.lock\fR file +available. +.SS "Configuration Discovery" +This command operates on system or user level, not project level. +This means that the local \fIconfiguration discovery\fR is ignored. +Instead, the configuration discovery begins at \fB$CARGO_HOME/config.toml\fR\&. +If the package is installed with \fB\-\-path $PATH\fR, the local configuration +will be used, beginning discovery at \fB$PATH/.cargo/config.toml\fR\&. +.SH "OPTIONS" +.SS "Install Options" +.sp +\fB\-\-vers\fR \fIversion\fR, +\fB\-\-version\fR \fIversion\fR +.RS 4 +Specify a version to install. This may be a \fIversion +requirement\fR , like \fB~1.2\fR, to have Cargo +select the newest version from the given requirement. If the version does not +have a requirement operator (such as \fB^\fR or \fB~\fR), then it must be in the form +\fIMAJOR.MINOR.PATCH\fR, and will install exactly that version; it is \fInot\fR +treated as a caret requirement like Cargo dependencies are. +.RE +.sp +\fB\-\-git\fR \fIurl\fR +.RS 4 +Git URL to install the specified crate from. +.RE +.sp +\fB\-\-branch\fR \fIbranch\fR +.RS 4 +Branch to use when installing from git. +.RE +.sp +\fB\-\-tag\fR \fItag\fR +.RS 4 +Tag to use when installing from git. +.RE +.sp +\fB\-\-rev\fR \fIsha\fR +.RS 4 +Specific commit to use when installing from git. +.RE +.sp +\fB\-\-path\fR \fIpath\fR +.RS 4 +Filesystem path to local crate to install from. +.RE +.sp +\fB\-\-list\fR +.RS 4 +List all installed packages and their versions. +.RE +.sp +\fB\-n\fR, +\fB\-\-dry\-run\fR +.RS 4 +(unstable) Perform all checks without installing. +.RE +.sp +\fB\-f\fR, +\fB\-\-force\fR +.RS 4 +Force overwriting existing crates or binaries. This can be used if a package +has installed a binary with the same name as another package. This is also +useful if something has changed on the system that you want to rebuild with, +such as a newer version of \fBrustc\fR\&. +.RE +.sp +\fB\-\-no\-track\fR +.RS 4 +By default, Cargo keeps track of the installed packages with a metadata file +stored in the installation root directory. This flag tells Cargo not to use or +create that file. With this flag, Cargo will refuse to overwrite any existing +files unless the \fB\-\-force\fR flag is used. This also disables Cargo\[cq]s ability to +protect against multiple concurrent invocations of Cargo installing at the +same time. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Install only the specified binary. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Install all binaries. This is the default behavior. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Install only the specified example. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Install all examples. +.RE +.sp +\fB\-\-root\fR \fIdir\fR +.RS 4 +Directory to install packages into. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.sp +\fB\-\-index\fR \fIindex\fR +.RS 4 +The URL of the registry index to use. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Install for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to a new temporary folder located in the +temporary directory of the platform. +.sp +When using \fB\-\-path\fR, by default it will use \fBtarget\fR directory in the workspace +of the local crate unless \fB\-\-target\-dir\fR +is specified. +.RE +.sp +\fB\-\-debug\fR +.RS 4 +Build with the \fBdev\fR profile instead of the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Install with the given profile. +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Install or upgrade a package from crates.io: +.sp +.RS 4 +.nf +cargo install ripgrep +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Install or reinstall the package in the current directory: +.sp +.RS 4 +.nf +cargo install \-\-path . +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'View the list of installed packages: +.sp +.RS 4 +.nf +cargo install \-\-list +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-uninstall\fR(1), \fBcargo\-search\fR(1), \fBcargo\-publish\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-locate-project.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-locate-project.1 new file mode 100644 index 000000000..83f7876a4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-locate-project.1 @@ -0,0 +1,150 @@ +'\" t +.TH "CARGO\-LOCATE\-PROJECT" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-locate\-project \[em] Print a JSON representation of a Cargo.toml file\[cq]s location +.SH "SYNOPSIS" +\fBcargo locate\-project\fR [\fIoptions\fR] +.SH "DESCRIPTION" +This command will print a JSON object to stdout with the full path to the manifest. The +manifest is found by searching upward for a file named \fBCargo.toml\fR starting from the current +working directory. +.sp +If the project happens to be a part of a workspace, the manifest of the project, rather than +the workspace root, is output. This can be overridden by the \fB\-\-workspace\fR flag. The root +workspace is found by traversing further upward or by using the field \fBpackage.workspace\fR after +locating the manifest of a workspace member. +.SH "OPTIONS" +.sp +\fB\-\-workspace\fR +.RS 4 +Locate the \fBCargo.toml\fR at the root of the workspace, as opposed to the current +workspace member. +.RE +.SS "Display Options" +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The representation in which to print the project location. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (default): JSON object with the path under the key \[lq]root\[rq]\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBplain\fR: Just the path. +.RE +.RE +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Display the path to the manifest based on the current directory: +.sp +.RS 4 +.nf +cargo locate\-project +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-metadata\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-login.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-login.1 new file mode 100644 index 000000000..55f7189b8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-login.1 @@ -0,0 +1,154 @@ +'\" t +.TH "CARGO\-LOGIN" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-login \[em] Log in to a registry +.SH "SYNOPSIS" +\fBcargo login\fR [\fIoptions\fR] [\fB\-\-\fR \fIargs\fR] +.SH "DESCRIPTION" +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 +All the arguments following the two dashes (\fB\-\-\fR) are passed to the credential provider. +.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 +The \fItoken\fR will be read from stdin. +.sp +The API token for crates.io may be retrieved from \&. +.sp +Take care to keep the token secret, it should not be shared with anyone else. +.SH "OPTIONS" +.SS "Login Options" +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Save the token for the default registry: +.sp +.RS 4 +.nf +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/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-logout.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-logout.1 new file mode 100644 index 000000000..1611d5435 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-logout.1 @@ -0,0 +1,153 @@ +'\" t +.TH "CARGO\-LOGOUT" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-logout \[em] Remove an API token from the registry locally +.SH "SYNOPSIS" +\fBcargo logout\fR [\fIoptions\fR] +.SH "DESCRIPTION" +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 +\fI\f(BIregistry.default\fI\fR , which defaults +to ). +.sp +This will not revoke the token on the server. If you need to revoke the token, +visit the registry website and follow its instructions (see + to revoke the token for ). +.SH "OPTIONS" +.SS "Logout Options" +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Remove the default registry token: +.sp +.RS 4 +.nf +cargo logout +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Remove the token for a specific registry: +.sp +.RS 4 +.nf +cargo logout \-\-registry my\-registry +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-login\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-metadata.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-metadata.1 new file mode 100644 index 000000000..9560e645e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-metadata.1 @@ -0,0 +1,563 @@ +'\" t +.TH "CARGO\-METADATA" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-metadata \[em] Machine\-readable metadata about the current package +.SH "SYNOPSIS" +\fBcargo metadata\fR [\fIoptions\fR] +.SH "DESCRIPTION" +Output JSON to stdout containing information about the workspace members and +resolved dependencies of the current package. +.sp +The output format is subject to change in future versions of Cargo. It +is recommended to include the \fB\-\-format\-version\fR flag to future\-proof your code +and ensure the output is in the format you are expecting. For more on the +expectations, see \[lq]Compatibility\[rq]\&. +.sp +See the \fIcargo_metadata crate\fR +for a Rust API for reading the metadata. +.SH "OUTPUT FORMAT" +.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 +considered as incompatible: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBAdding new fields\fR \[em] New fields will be added when needed. Reserving this +helps Cargo evolve without bumping the format version too often. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBAdding new values for enum\-like fields\fR \[em] Same as adding new fields. It +keeps metadata evolving without stagnation. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBChanging opaque representations\fR \[em] The inner representations of some +fields are implementation details. For example, fields related to +\[lq]Source ID\[rq] are treated as opaque identifiers to differentiate packages or +sources. Consumers shouldn\[cq]t rely on those representations unless specified. +.RE +.SS "JSON format" +The JSON output has the following format: +.sp +.RS 4 +.nf +{ + /* Array of all packages in the workspace. + It also includes all feature\-enabled dependencies unless \-\-no\-deps is used. + */ + "packages": [ + { + /* The name of the package. */ + "name": "my\-package", + /* The version of the package. */ + "version": "0.1.0", + /* The Package ID for referring to the + package within the document and as the `\-\-package` argument to many commands + */ + "id": "file:///path/to/my\-package#0.1.0", + /* The license value from the manifest, or null. */ + "license": "MIT/Apache\-2.0", + /* The license\-file value from the manifest, or null. */ + "license_file": "LICENSE", + /* The description value from the manifest, or null. */ + "description": "Package description.", + /* The source ID of the package, an "opaque" identifier representing + where a package is retrieved from. See "Compatibility" above for + the stability guarantee. + + This is null for path dependencies and workspace members. + + For other dependencies, it is a string with the format: + \- "registry+URL" for registry\-based dependencies. + Example: "registry+https://github.com/rust\-lang/crates.io\-index" + \- "git+URL" for git\-based dependencies. + Example: "git+https://github.com/rust\-lang/cargo?rev=5e85ba14aaa20f8133863373404cb0af69eeef2c#5e85ba14aaa20f8133863373404cb0af69eeef2c" + \- "sparse+URL" for dependencies from a sparse registry + Example: "sparse+https://my\-sparse\-registry.org" + + The value after the `+` is not explicitly defined, and may change + between versions of Cargo and may not directly correlate to other + things, such as registry definitions in a config file. New source + kinds may be added in the future which will have different `+` + prefixed identifiers. + */ + "source": null, + /* Array of dependencies declared in the package's manifest. */ + "dependencies": [ + { + /* The name of the dependency. */ + "name": "bitflags", + /* The source ID of the dependency. May be null, see + description for the package source. + */ + "source": "registry+https://github.com/rust\-lang/crates.io\-index", + /* The version requirement for the dependency. + Dependencies without a version requirement have a value of "*". + */ + "req": "^1.0", + /* The dependency kind. + "dev", "build", or null for a normal dependency. + */ + "kind": null, + /* If the dependency is renamed, this is the new name for + the dependency as a string. null if it is not renamed. + */ + "rename": null, + /* Boolean of whether or not this is an optional dependency. */ + "optional": false, + /* Boolean of whether or not default features are enabled. */ + "uses_default_features": true, + /* Array of features enabled. */ + "features": [], + /* The target platform for the dependency. + null if not a target dependency. + */ + "target": "cfg(windows)", + /* The file system path for a local path dependency. + not present if not a path dependency. + */ + "path": "/path/to/dep", + /* A string of the URL of the registry this dependency is from. + If not specified or null, the dependency is from the default + registry (crates.io). + */ + "registry": null, + /* (unstable) Boolean flag of whether or not this is a pulbic + dependency. This field is only present when + `\-Zpublic\-dependency` is enabled. + */ + "public": false + } + ], + /* Array of Cargo targets. */ + "targets": [ + { + /* Array of target kinds. + \- lib targets list the `crate\-type` values from the + manifest such as "lib", "rlib", "dylib", + "proc\-macro", etc. (default ["lib"]) + \- binary is ["bin"] + \- example is ["example"] + \- integration test is ["test"] + \- benchmark is ["bench"] + \- build script is ["custom\-build"] + */ + "kind": [ + "bin" + ], + /* Array of crate types. + \- lib and example libraries list the `crate\-type` values + from the manifest such as "lib", "rlib", "dylib", + "proc\-macro", etc. (default ["lib"]) + \- all other target kinds are ["bin"] + */ + "crate_types": [ + "bin" + ], + /* The name of the target. + For lib targets, dashes will be replaced with underscores. + */ + "name": "my\-package", + /* Absolute path to the root source file of the target. */ + "src_path": "/path/to/my\-package/src/main.rs", + /* The Rust edition of the target. + Defaults to the package edition. + */ + "edition": "2018", + /* Array of required features. + This property is not included if no required features are set. + */ + "required\-features": ["feat1"], + /* Whether the target should be documented by `cargo doc`. */ + "doc": true, + /* Whether or not this target has doc tests enabled, and + the target is compatible with doc testing. + */ + "doctest": false, + /* Whether or not this target should be built and run with `\-\-test` + */ + "test": true + } + ], + /* Set of features defined for the package. + Each feature maps to an array of features or dependencies it + enables. + */ + "features": { + "default": [ + "feat1" + ], + "feat1": [], + "feat2": [] + }, + /* Absolute path to this package's manifest. */ + "manifest_path": "/path/to/my\-package/Cargo.toml", + /* Package metadata. + This is null if no metadata is specified. + */ + "metadata": { + "docs": { + "rs": { + "all\-features": true + } + } + }, + /* List of registries to which this package may be published. + Publishing is unrestricted if null, and forbidden if an empty array. */ + "publish": [ + "crates\-io" + ], + /* Array of authors from the manifest. + Empty array if no authors specified. + */ + "authors": [ + "Jane Doe " + ], + /* Array of categories from the manifest. */ + "categories": [ + "command\-line\-utilities" + ], + /* Optional string that is the default binary picked by cargo run. */ + "default_run": null, + /* Optional string that is the minimum supported rust version */ + "rust_version": "1.56", + /* Array of keywords from the manifest. */ + "keywords": [ + "cli" + ], + /* The readme value from the manifest or null if not specified. */ + "readme": "README.md", + /* The repository value from the manifest or null if not specified. */ + "repository": "https://github.com/rust\-lang/cargo", + /* The homepage value from the manifest or null if not specified. */ + "homepage": "https://rust\-lang.org", + /* The documentation value from the manifest or null if not specified. */ + "documentation": "https://doc.rust\-lang.org/stable/std", + /* The default edition of the package. + Note that individual targets may have different editions. + */ + "edition": "2018", + /* Optional string that is the name of a native library the package + is linking to. + */ + "links": null, + } + ], + /* Array of members of the workspace. + Each entry is the Package ID for the package. + */ + "workspace_members": [ + "file:///path/to/my\-package#0.1.0", + ], + /* Array of default members of the workspace. + Each entry is the Package ID for the package. + */ + "workspace_default_members": [ + "file:///path/to/my\-package#0.1.0", + ], + // The resolved dependency graph for the entire workspace. The enabled + // features are based on the enabled features for the "current" package. + // Inactivated optional dependencies are not listed. + // + // This is null if \-\-no\-deps is specified. + // + // By default, this includes all dependencies for all target platforms. + // The `\-\-filter\-platform` flag may be used to narrow to a specific + // target triple. + "resolve": { + /* Array of nodes within the dependency graph. + Each node is a package. + */ + "nodes": [ + { + /* The Package ID of this node. */ + "id": "file:///path/to/my\-package#0.1.0", + /* The dependencies of this package, an array of Package IDs. */ + "dependencies": [ + "https://github.com/rust\-lang/crates.io\-index#bitflags@1.0.4" + ], + /* The dependencies of this package. This is an alternative to + "dependencies" which contains additional information. In + particular, this handles renamed dependencies. + */ + "deps": [ + { + /* The name of the dependency's library target. + If this is a renamed dependency, this is the new + name. + */ + "name": "bitflags", + /* The Package ID of the dependency. */ + "pkg": "https://github.com/rust\-lang/crates.io\-index#bitflags@1.0.4" + /* Array of dependency kinds. Added in Cargo 1.40. */ + "dep_kinds": [ + { + /* The dependency kind. + "dev", "build", or null for a normal dependency. + */ + "kind": null, + /* The target platform for the dependency. + null if not a target dependency. + */ + "target": "cfg(windows)" + } + ] + } + ], + /* Array of features enabled on this package. */ + "features": [ + "default" + ] + } + ], + /* The package in the current working directory (if \-\-manifest\-path is not given). + This is null if there is a virtual workspace. Otherwise it is + the Package ID of the package. + */ + "root": "file:///path/to/my\-package#0.1.0", + }, + /* The absolute path to the build directory where Cargo places its output. */ + "target_directory": "/path/to/my\-package/target", + /* The version of the schema for this metadata structure. + This will be changed if incompatible changes are ever made. + */ + "version": 1, + /* The absolute path to the root of the workspace. */ + "workspace_root": "/path/to/my\-package" + /* Workspace metadata. + This is null if no metadata is specified. */ + "metadata": { + "docs": { + "rs": { + "all\-features": true + } + } + } +} +.fi +.RE +.sp +Notes: +.sp +.RS 4 +\h'-04'\(bu\h'+03'For \fB"id"\fR field syntax, see \fIPackage ID Specifications\fR in the reference. +.RE +.SH "OPTIONS" +.SS "Output Options" +.sp +\fB\-\-no\-deps\fR +.RS 4 +Output information only about the workspace members and don\[cq]t fetch +dependencies. +.RE +.sp +\fB\-\-format\-version\fR \fIversion\fR +.RS 4 +Specify the version of the output format to use. Currently \fB1\fR is the only +possible value. +.RE +.sp +\fB\-\-filter\-platform\fR \fItriple\fR +.RS 4 +This filters the \fBresolve\fR output to only include dependencies for the +given \fItarget triple\fR \&. +Without this flag, the resolve includes all targets. +.sp +Note that the dependencies listed in the \[lq]packages\[rq] array still includes all +dependencies. Each package definition is intended to be an unaltered +reproduction of the information within \fBCargo.toml\fR\&. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Output JSON about the current package: +.sp +.RS 4 +.nf +cargo metadata \-\-format\-version=1 +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-pkgid\fR(1), \fIPackage ID Specifications\fR , \fIJSON messages\fR diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-new.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-new.1 new file mode 100644 index 000000000..6a33a8a7c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-new.1 @@ -0,0 +1,166 @@ +'\" t +.TH "CARGO\-NEW" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-new \[em] Create a new Cargo package +.SH "SYNOPSIS" +\fBcargo new\fR [\fIoptions\fR] \fIpath\fR +.SH "DESCRIPTION" +This command will create a new Cargo package in the given directory. This +includes a simple template with a \fBCargo.toml\fR manifest, sample source file, +and a VCS ignore file. If the directory is not already in a VCS repository, +then a new repository is created (see \fB\-\-vcs\fR below). +.sp +See \fBcargo\-init\fR(1) for a similar command which will create a new manifest +in an existing directory. +.SH "OPTIONS" +.SS "New Options" +.sp +\fB\-\-bin\fR +.RS 4 +Create a package with a binary target (\fBsrc/main.rs\fR). +This is the default behavior. +.RE +.sp +\fB\-\-lib\fR +.RS 4 +Create a package with a library target (\fBsrc/lib.rs\fR). +.RE +.sp +\fB\-\-edition\fR \fIedition\fR +.RS 4 +Specify the Rust edition to use. Default is 2024. +Possible values: 2015, 2018, 2021, 2024 +.RE +.sp +\fB\-\-name\fR \fIname\fR +.RS 4 +Set the package name. Defaults to the directory name. +.RE +.sp +\fB\-\-vcs\fR \fIvcs\fR +.RS 4 +Initialize a new VCS repository for the given version control system (git, +hg, pijul, or fossil) or do not initialize any version control at all +(none). If not specified, defaults to \fBgit\fR or the configuration value +\fBcargo\-new.vcs\fR, or \fBnone\fR if already inside a VCS repository. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +This sets the \fBpublish\fR field in \fBCargo.toml\fR to the given registry name +which will restrict publishing only to that registry. +.sp +Registry names are defined in \fICargo config files\fR \&. +If not specified, the default registry defined by the \fBregistry.default\fR +config key is used. If the default registry is not set and \fB\-\-registry\fR is not +used, the \fBpublish\fR field will not be set which means that publishing will not +be restricted. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Create a binary Cargo package in the given directory: +.sp +.RS 4 +.nf +cargo new foo +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-init\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-owner.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-owner.1 new file mode 100644 index 000000000..36e0d4d68 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-owner.1 @@ -0,0 +1,197 @@ +'\" t +.TH "CARGO\-OWNER" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-owner \[em] Manage the owners of a crate on the registry +.SH "SYNOPSIS" +\fBcargo owner\fR [\fIoptions\fR] \fB\-\-add\fR \fIlogin\fR [\fIcrate\fR] +.br +\fBcargo owner\fR [\fIoptions\fR] \fB\-\-remove\fR \fIlogin\fR [\fIcrate\fR] +.br +\fBcargo owner\fR [\fIoptions\fR] \fB\-\-list\fR [\fIcrate\fR] +.SH "DESCRIPTION" +This command will modify the owners for a crate on the registry. Owners of a +crate can upload new versions and yank old versions. Non\-team owners can also +modify the set of owners, so take care! +.sp +This command requires you to be authenticated with either the \fB\-\-token\fR option +or using \fBcargo\-login\fR(1). +.sp +If the crate name is not specified, it will use the package name from the +current directory. +.sp +See \fIthe reference\fR for more +information about owners and publishing. +.SH "OPTIONS" +.SS "Owner Options" +.sp +\fB\-a\fR, +\fB\-\-add\fR \fIlogin\fR\[u2026] +.RS 4 +Invite the given user or team as an owner. +.RE +.sp +\fB\-r\fR, +\fB\-\-remove\fR \fIlogin\fR\[u2026] +.RS 4 +Remove the given user or team as an owner. +.RE +.sp +\fB\-l\fR, +\fB\-\-list\fR +.RS 4 +List owners of a crate. +.RE +.sp +\fB\-\-token\fR \fItoken\fR +.RS 4 +API token to use when authenticating. This overrides the token stored in +the credentials file (which is created by \fBcargo\-login\fR(1)). +.sp +\fICargo config\fR environment variables can be +used to override the tokens stored in the credentials file. The token for +crates.io may be specified with the \fBCARGO_REGISTRY_TOKEN\fR environment +variable. Tokens for other registries may be specified with environment +variables of the form \fBCARGO_REGISTRIES_NAME_TOKEN\fR where \fBNAME\fR is the name +of the registry in all capital letters. +.RE +.sp +\fB\-\-index\fR \fIindex\fR +.RS 4 +The URL of the registry index to use. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'List owners of a package: +.sp +.RS 4 +.nf +cargo owner \-\-list foo +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Invite an owner to a package: +.sp +.RS 4 +.nf +cargo owner \-\-add username foo +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Remove an owner from a package: +.sp +.RS 4 +.nf +cargo owner \-\-remove username foo +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-login\fR(1), \fBcargo\-publish\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-package.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-package.1 new file mode 100644 index 000000000..25dec5933 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-package.1 @@ -0,0 +1,414 @@ +'\" t +.TH "CARGO\-PACKAGE" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-package \[em] Assemble the local package into a distributable tarball +.SH "SYNOPSIS" +\fBcargo package\fR [\fIoptions\fR] +.SH "DESCRIPTION" +This command will create a distributable, compressed \fB\&.crate\fR file with the +source code of the package in the current directory. The resulting file will be +stored in the \fBtarget/package\fR directory. This performs the following steps: +.sp +.RS 4 +\h'-04' 1.\h'+01'Load and check the current workspace, performing some basic checks. +.sp +.RS 4 +\h'-04'\(bu\h'+03'Path dependencies are not allowed unless they have a version key. Cargo +will ignore the path key for dependencies in published packages. +\fBdev\-dependencies\fR do not have this restriction. +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Create the compressed \fB\&.crate\fR file. +.sp +.RS 4 +\h'-04'\(bu\h'+03'The original \fBCargo.toml\fR file is rewritten and normalized. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB[patch]\fR, \fB[replace]\fR, and \fB[workspace]\fR sections are removed from the +manifest. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBCargo.lock\fR is always included. When missing, a new lock file will be +generated. \fBcargo\-install\fR(1) will use the packaged lock file if +the \fB\-\-locked\fR flag is used. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'A \fB\&.cargo_vcs_info.json\fR file is included that contains information +about the current VCS checkout hash if available, as well as a flag if the +worktree is dirty. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Symlinks are flattened to their target files. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Files and directories are included or excluded based on rules mentioned in +\fIthe \f(BI[include]\fI and \f(BI[exclude]\fI fields\fR \&. +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Extract the \fB\&.crate\fR file and build it to verify it can build. +.sp +.RS 4 +\h'-04'\(bu\h'+03'This will rebuild your package from scratch to ensure that it can be +built from a pristine state. The \fB\-\-no\-verify\fR flag can be used to skip +this step. +.RE +.RE +.sp +.RS 4 +\h'-04' 4.\h'+01'Check that build scripts did not modify any source files. +.RE +.sp +The list of files included can be controlled with the \fBinclude\fR and \fBexclude\fR +fields in the manifest. +.sp +See \fIthe reference\fR for more details about +packaging and publishing. +.SS ".cargo_vcs_info.json format" +Will generate a \fB\&.cargo_vcs_info.json\fR in the following format +.sp +.RS 4 +.nf +{ + "git": { + "sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302", + "dirty": true + }, + "path_in_vcs": "" +} +.fi +.RE +.sp +\fBdirty\fR indicates that the Git worktree was dirty when the package +was built. +.sp +\fBpath_in_vcs\fR will be set to a repo\-relative path for packages +in subdirectories of the version control repository. +.sp +The compatibility of this file is maintained under the same policy +as the JSON output of \fBcargo\-metadata\fR(1). +.sp +Note that this file provides a best\-effort snapshot of the VCS information. +However, the provenance of the package is not verified. +There is no guarantee that the source code in the tarball matches the VCS information. +.SH "OPTIONS" +.SS "Package Options" +.sp +\fB\-l\fR, +\fB\-\-list\fR +.RS 4 +Print files included in a package without making one. +.RE +.sp +\fB\-\-no\-verify\fR +.RS 4 +Don\[cq]t verify the contents by building them. +.RE +.sp +\fB\-\-no\-metadata\fR +.RS 4 +Ignore warnings about a lack of human\-usable metadata (such as the description +or the license). +.RE +.sp +\fB\-\-allow\-dirty\fR +.RS 4 +Allow working directories with uncommitted VCS changes to be packaged. +.RE +.sp +\fB\-\-index\fR \fIindex\fR +.RS 4 +The URL of the registry index to use. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to package for; see \fBcargo publish \-\-help\fR for more details +about configuration of registry names. The packages will not be published +to this registry, but if we are packaging multiple inter\-dependent crates, +lock\-files will be generated under the assumption that dependencies will be +published to this registry. +.RE +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Package only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Package all members in the workspace. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Package for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Create a compressed \fB\&.crate\fR file of the current package: +.sp +.RS 4 +.nf +cargo package +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-publish\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-pkgid.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-pkgid.1 new file mode 100644 index 000000000..355ffcc73 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-pkgid.1 @@ -0,0 +1,272 @@ +'\" t +.TH "CARGO\-PKGID" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-pkgid \[em] Print a fully qualified package specification +.SH "SYNOPSIS" +\fBcargo pkgid\fR [\fIoptions\fR] [\fIspec\fR] +.SH "DESCRIPTION" +Given a \fIspec\fR argument, print out the fully qualified package ID specifier +for a package or dependency in the current workspace. This command will +generate an error if \fIspec\fR is ambiguous as to which package it refers to in +the dependency graph. If no \fIspec\fR is given, then the specifier for the local +package is printed. +.sp +This command requires that a lockfile is available and dependencies have been +fetched. +.sp +A package specifier consists of a name, version, and source URL. You are +allowed to use partial specifiers to succinctly match a specific package as +long as it matches only one package. This specifier is also used by other parts +in Cargo, such as \fBcargo\-metadata\fR(1) and \fIJSON messages\fR emitted by Cargo. +.sp +The format of a \fIspec\fR can be one of the following: + +.TS +allbox tab(:); +lt lt. +T{ +SPEC Structure +T}:T{ +Example SPEC +T} +T{ +\fIname\fR +T}:T{ +\fBbitflags\fR +T} +T{ +\fIname\fR\fB@\fR\fIversion\fR +T}:T{ +\fBbitflags@1.0.4\fR +T} +T{ +\fIurl\fR +T}:T{ +\fBhttps://github.com/rust\-lang/cargo\fR +T} +T{ +\fIurl\fR\fB#\fR\fIversion\fR +T}:T{ +\fBhttps://github.com/rust\-lang/cargo#0.33.0\fR +T} +T{ +\fIurl\fR\fB#\fR\fIname\fR +T}:T{ +\fBhttps://github.com/rust\-lang/crates.io\-index#bitflags\fR +T} +T{ +\fIurl\fR\fB#\fR\fIname\fR\fB@\fR\fIversion\fR +T}:T{ +\fBhttps://github.com/rust\-lang/cargo#crates\-io@0.21.0\fR +T} +.TE +.sp +.sp +The specification grammar can be found in chapter \fIPackage ID Specifications\fR \&. +.SH "OPTIONS" +.SS "Package Selection" +.sp +\fB\-p\fR \fIspec\fR, +\fB\-\-package\fR \fIspec\fR +.RS 4 +Get the package ID for the given package instead of the current package. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Retrieve package specification for \fBfoo\fR package: +.sp +.RS 4 +.nf +cargo pkgid foo +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Retrieve package specification for version 1.0.0 of \fBfoo\fR: +.sp +.RS 4 +.nf +cargo pkgid foo@1.0.0 +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Retrieve package specification for \fBfoo\fR from crates.io: +.sp +.RS 4 +.nf +cargo pkgid https://github.com/rust\-lang/crates.io\-index#foo +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 4.\h'+01'Retrieve package specification for \fBfoo\fR from a local package: +.sp +.RS 4 +.nf +cargo pkgid file:///path/to/local/package#foo +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-generate\-lockfile\fR(1), \fBcargo\-metadata\fR(1), +\fIPackage ID Specifications\fR , \fIJSON messages\fR diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-publish.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-publish.1 new file mode 100644 index 000000000..613a1ecdb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-publish.1 @@ -0,0 +1,382 @@ +'\" t +.TH "CARGO\-PUBLISH" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-publish \[em] Upload a package to the registry +.SH "SYNOPSIS" +\fBcargo publish\fR [\fIoptions\fR] +.SH "DESCRIPTION" +This command will create a distributable, compressed \fB\&.crate\fR file with the +source code of the package in the current directory and upload it to a +registry. The default registry is \&. This performs the +following steps: +.sp +.RS 4 +\h'-04' 1.\h'+01'Performs a few checks, including: +.sp +.RS 4 +\h'-04'\(bu\h'+03'Checks the \fBpackage.publish\fR key in the manifest for restrictions on +which registries you are allowed to publish to. +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Create a \fB\&.crate\fR file by following the steps in \fBcargo\-package\fR(1). +.RE +.sp +.RS 4 +\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 +or using \fBcargo\-login\fR(1). +.sp +See \fIthe reference\fR for more details about +packaging and publishing. +.SH "OPTIONS" +.SS "Publish Options" +.sp +\fB\-\-dry\-run\fR +.RS 4 +Perform all checks without uploading. +.RE +.sp +\fB\-\-token\fR \fItoken\fR +.RS 4 +API token to use when authenticating. This overrides the token stored in +the credentials file (which is created by \fBcargo\-login\fR(1)). +.sp +\fICargo config\fR environment variables can be +used to override the tokens stored in the credentials file. The token for +crates.io may be specified with the \fBCARGO_REGISTRY_TOKEN\fR environment +variable. Tokens for other registries may be specified with environment +variables of the form \fBCARGO_REGISTRIES_NAME_TOKEN\fR where \fBNAME\fR is the name +of the registry in all capital letters. +.RE +.sp +\fB\-\-no\-verify\fR +.RS 4 +Don\[cq]t verify the contents by building them. +.RE +.sp +\fB\-\-allow\-dirty\fR +.RS 4 +Allow working directories with uncommitted VCS changes to be packaged. +.RE +.sp +\fB\-\-index\fR \fIindex\fR +.RS 4 +The URL of the registry index to use. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to publish to. Registry names are defined in \fICargo +config files\fR \&. If not specified, and there is a +\fI\f(BIpackage.publish\fI\fR field in +\fBCargo.toml\fR with a single registry, then it will publish to that registry. +Otherwise it will use the default registry, which is defined by the +\fI\f(BIregistry.default\fI\fR config key +which defaults to \fBcrates\-io\fR\&. +.RE +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +Selecting more than one package is unstable and available only on the +\fInightly channel\fR +and requires the \fB\-Z package\-workspace\fR flag to enable. +See for more information. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Publish only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +Selecting more than one package with this option is unstable and available only +on the +[nightly channel](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html) +and requires the `-Z package-workspace` flag to enable. +See for more information. +.sp +\fB\-\-workspace\fR +.RS 4 +Publish all members in the workspace. +.sp +This option is unstable and available only on the +\fInightly channel\fR +and requires the \fB\-Z package\-workspace\fR flag to enable. +See for more information. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.sp +This option is unstable and available only on the +\fInightly channel\fR +and requires the \fB\-Z package\-workspace\fR flag to enable. +See for more information. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Publish for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Publish the current package: +.sp +.RS 4 +.nf +cargo publish +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-package\fR(1), \fBcargo\-login\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-remove.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-remove.1 new file mode 100644 index 000000000..2ab2dfc73 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-remove.1 @@ -0,0 +1,228 @@ +'\" t +.TH "CARGO\-REMOVE" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-remove \[em] Remove dependencies from a Cargo.toml manifest file +.SH "SYNOPSIS" +\fBcargo remove\fR [\fIoptions\fR] \fIdependency\fR\[u2026] +.SH "DESCRIPTION" +Remove one or more dependencies from a \fBCargo.toml\fR manifest. +.SH "OPTIONS" +.SS "Section options" +.sp +\fB\-\-dev\fR +.RS 4 +Remove as a \fIdevelopment dependency\fR \&. +.RE +.sp +\fB\-\-build\fR +.RS 4 +Remove as a \fIbuild dependency\fR \&. +.RE +.sp +\fB\-\-target\fR \fItarget\fR +.RS 4 +Remove as a dependency to the \fIgiven target platform\fR \&. +.sp +To avoid unexpected shell expansions, you may use quotes around each target, e.g., \fB\-\-target 'cfg(unix)'\fR\&. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-\-dry\-run\fR +.RS 4 +Don\[cq]t actually write to the manifest. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Package Selection" +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Package to remove from. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Remove \fBregex\fR as a dependency +.sp +.RS 4 +.nf +cargo remove regex +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Remove \fBtrybuild\fR as a dev\-dependency +.sp +.RS 4 +.nf +cargo remove \-\-dev trybuild +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Remove \fBnom\fR from the \fBx86_64\-pc\-windows\-gnu\fR dependencies table +.sp +.RS 4 +.nf +cargo remove \-\-target x86_64\-pc\-windows\-gnu nom +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-add\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-report.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-report.1 new file mode 100644 index 000000000..24b630569 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-report.1 @@ -0,0 +1,48 @@ +'\" t +.TH "CARGO\-REPORT" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-report \[em] Generate and display various kinds of reports +.SH "SYNOPSIS" +\fBcargo report\fR \fItype\fR [\fIoptions\fR] +.SS "DESCRIPTION" +Displays a report of the given \fItype\fR \[em] currently, only \fBfuture\-incompat\fR is supported +.SH "OPTIONS" +.sp +\fB\-\-id\fR \fIid\fR +.RS 4 +Show the report with the specified Cargo\-generated id +.RE +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Only display a report for the specified package +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Display the latest future\-incompat report: +.sp +.RS 4 +.nf +cargo report future\-incompat +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Display the latest future\-incompat report for a specific package: +.sp +.RS 4 +.nf +cargo report future\-incompat \-\-package my\-dep:0.0.1 +.fi +.RE +.RE +.SH "SEE ALSO" +\fIFuture incompat report\fR +.sp +\fBcargo\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-run.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-run.1 new file mode 100644 index 000000000..0e6984214 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-run.1 @@ -0,0 +1,373 @@ +'\" t +.TH "CARGO\-RUN" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-run \[em] Run the current package +.SH "SYNOPSIS" +\fBcargo run\fR [\fIoptions\fR] [\fB\-\-\fR \fIargs\fR] +.SH "DESCRIPTION" +Run a binary or example of the local package. +.sp +All the arguments following the two dashes (\fB\-\-\fR) are passed to the binary to +run. If you\[cq]re passing arguments to both Cargo and the binary, the ones after +\fB\-\-\fR go to the binary, the ones before go to Cargo. +.sp +Unlike \fBcargo\-test\fR(1) and \fBcargo\-bench\fR(1), \fBcargo run\fR sets the +working directory of the binary executed to the current working directory, same +as if it was executed in the shell directly. +.SH "OPTIONS" +.SS "Package Selection" +By default, the package in the current working directory is selected. The \fB\-p\fR +flag can be used to choose a different package in a workspace. +.sp +\fB\-p\fR \fIspec\fR, +\fB\-\-package\fR \fIspec\fR +.RS 4 +The package to run. See \fBcargo\-pkgid\fR(1) for the SPEC +format. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo run\fR will run the binary +target. If there are multiple binary targets, you must pass a target flag to +choose one. Or, the \fBdefault\-run\fR field may be specified in the \fB[package]\fR +section of \fBCargo.toml\fR to choose the name of the binary to run by default. +.sp +\fB\-\-bin\fR \fIname\fR +.RS 4 +Run the specified binary. +.RE +.sp +\fB\-\-example\fR \fIname\fR +.RS 4 +Run the specified example. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Run for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Run optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Run with the given profile. +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Build the local package and run its main target (assuming only one binary): +.sp +.RS 4 +.nf +cargo run +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Run an example with extra arguments: +.sp +.RS 4 +.nf +cargo run \-\-example exname \-\- \-\-exoption exarg1 exarg2 +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-build\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustc.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustc.1 new file mode 100644 index 000000000..e33b4faba --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustc.1 @@ -0,0 +1,506 @@ +'\" t +.TH "CARGO\-RUSTC" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-rustc \[em] Compile the current package, and pass extra options to the compiler +.SH "SYNOPSIS" +\fBcargo rustc\fR [\fIoptions\fR] [\fB\-\-\fR \fIargs\fR] +.SH "DESCRIPTION" +The specified target for the current package (or package specified by \fB\-p\fR if +provided) will be compiled along with all of its dependencies. The specified +\fIargs\fR will all be passed to the final compiler invocation, not any of the +dependencies. Note that the compiler will still unconditionally receive +arguments such as \fB\-L\fR, \fB\-\-extern\fR, and \fB\-\-crate\-type\fR, and the specified +\fIargs\fR will simply be added to the compiler invocation. +.sp +See for documentation on rustc +flags. +.sp +This command requires that only one target is being compiled when additional +arguments are provided. If more than one target is available for the current +package the filters of \fB\-\-lib\fR, \fB\-\-bin\fR, etc, must be used to select which +target is compiled. +.sp +To pass flags to all compiler processes spawned by Cargo, use the \fBRUSTFLAGS\fR +\fIenvironment variable\fR or the +\fBbuild.rustflags\fR \fIconfig value\fR \&. +.SH "OPTIONS" +.SS "Package Selection" +By default, the package in the current working directory is selected. The \fB\-p\fR +flag can be used to choose a different package in a workspace. +.sp +\fB\-p\fR \fIspec\fR, +\fB\-\-package\fR \fIspec\fR +.RS 4 +The package to build. See \fBcargo\-pkgid\fR(1) for the SPEC +format. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo rustc\fR will build all +binary and library targets of the selected package. +.sp +Binary targets are automatically built if there is an integration test or +benchmark being selected to build. This allows an integration +test to execute the binary to exercise and test its behavior. +The \fBCARGO_BIN_EXE_\fR +\fIenvironment variable\fR +is set when the integration test is built so that it can use the +\fI\f(BIenv\fI macro\fR to locate the +executable. +.sp +Passing target selection flags will build only the specified +targets. +.sp +Note that \fB\-\-bin\fR, \fB\-\-example\fR, \fB\-\-test\fR and \fB\-\-bench\fR flags also +support common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your +shell accidentally expanding glob patterns before Cargo handles them, you must +use single quotes or double quotes around each glob pattern. +.sp +\fB\-\-lib\fR +.RS 4 +Build the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Build the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Build all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Build the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Build all example targets. +.RE +.sp +\fB\-\-test\fR \fIname\fR\[u2026] +.RS 4 +Build the specified integration test. This flag may be specified +multiple times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-tests\fR +.RS 4 +Build all targets that have the \fBtest = true\fR manifest +flag set. By default this includes the library and binaries built as +unittests, and integration tests. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +unittest, and once as a dependency for binaries, integration tests, etc.). +Targets may be enabled or disabled by setting the \fBtest\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-bench\fR \fIname\fR\[u2026] +.RS 4 +Build the specified benchmark. This flag may be specified multiple +times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-benches\fR +.RS 4 +Build all targets that have the \fBbench = true\fR +manifest flag set. By default this includes the library and binaries built +as benchmarks, and bench targets. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +benchmark, and once as a dependency for binaries, benchmarks, etc.). +Targets may be enabled or disabled by setting the \fBbench\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-all\-targets\fR +.RS 4 +Build all targets. This is equivalent to specifying \fB\-\-lib \-\-bins \-\-tests \-\-benches \-\-examples\fR\&. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Build for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Build optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Build with the given profile. +.sp +The \fBrustc\fR subcommand will treat the following named profiles with special behaviors: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBcheck\fR \[em] Builds in the same way as the \fBcargo\-check\fR(1) command with +the \fBdev\fR profile. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBtest\fR \[em] Builds in the same way as the \fBcargo\-test\fR(1) command, +enabling building in test mode which will enable tests and enable the \fBtest\fR +cfg option. See \fIrustc +tests\fR for more detail. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBbench\fR \[em] Builds in the same was as the \fBcargo\-bench\fR(1) command, +similar to the \fBtest\fR profile. +.RE +.sp +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.sp +\fB\-\-crate\-type\fR \fIcrate\-type\fR +.RS 4 +Build for the given crate type. This flag accepts a comma\-separated list of +1 or more crate types, of which the allowed values are the same as \fBcrate\-type\fR +field in the manifest for configuring a Cargo target. See +\fI\f(BIcrate\-type\fI field\fR +for possible values. +.sp +If the manifest contains a list, and \fB\-\-crate\-type\fR is provided, +the command\-line argument value will override what is in the manifest. +.sp +This flag only works when building a \fBlib\fR or \fBexample\fR library target. +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 +.RS 4 +Displays a future\-incompat report for any future\-incompatible warnings +produced during execution of this command +.sp +See \fBcargo\-report\fR(1) +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Check if your package (not including dependencies) uses unsafe code: +.sp +.RS 4 +.nf +cargo rustc \-\-lib \-\- \-D unsafe\-code +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Try an experimental flag on the nightly compiler, such as this which prints +the size of every type: +.sp +.RS 4 +.nf +cargo rustc \-\-lib \-\- \-Z print\-type\-sizes +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Override \fBcrate\-type\fR field in Cargo.toml with command\-line option: +.sp +.RS 4 +.nf +cargo rustc \-\-lib \-\-crate\-type lib,cdylib +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-build\fR(1), \fBrustc\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustdoc.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustdoc.1 new file mode 100644 index 000000000..5b85f5457 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-rustdoc.1 @@ -0,0 +1,461 @@ +'\" t +.TH "CARGO\-RUSTDOC" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-rustdoc \[em] Build a package\[cq]s documentation, using specified custom flags +.SH "SYNOPSIS" +\fBcargo rustdoc\fR [\fIoptions\fR] [\fB\-\-\fR \fIargs\fR] +.SH "DESCRIPTION" +The specified target for the current package (or package specified by \fB\-p\fR if +provided) will be documented with the specified \fIargs\fR being passed to the +final rustdoc invocation. Dependencies will not be documented as part of this +command. Note that rustdoc will still unconditionally receive arguments such +as \fB\-L\fR, \fB\-\-extern\fR, and \fB\-\-crate\-type\fR, and the specified \fIargs\fR will simply +be added to the rustdoc invocation. +.sp +See for documentation on rustdoc +flags. +.sp +This command requires that only one target is being compiled when additional +arguments are provided. If more than one target is available for the current +package the filters of \fB\-\-lib\fR, \fB\-\-bin\fR, etc, must be used to select which +target is compiled. +.sp +To pass flags to all rustdoc processes spawned by Cargo, use the +\fBRUSTDOCFLAGS\fR \fIenvironment variable\fR +or the \fBbuild.rustdocflags\fR \fIconfig value\fR \&. +.SH "OPTIONS" +.SS "Documentation Options" +.sp +\fB\-\-open\fR +.RS 4 +Open the docs in a browser after building them. This will use your default +browser unless you define another one in the \fBBROWSER\fR environment variable +or use the \fI\f(BIdoc.browser\fI\fR configuration +option. +.RE +.SS "Package Selection" +By default, the package in the current working directory is selected. The \fB\-p\fR +flag can be used to choose a different package in a workspace. +.sp +\fB\-p\fR \fIspec\fR, +\fB\-\-package\fR \fIspec\fR +.RS 4 +The package to document. See \fBcargo\-pkgid\fR(1) for the SPEC +format. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo rustdoc\fR will document all +binary and library targets of the selected package. The binary will be skipped +if its name is the same as the lib target. Binaries are skipped if they have +\fBrequired\-features\fR that are missing. +.sp +Passing target selection flags will document only the specified +targets. +.sp +Note that \fB\-\-bin\fR, \fB\-\-example\fR, \fB\-\-test\fR and \fB\-\-bench\fR flags also +support common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your +shell accidentally expanding glob patterns before Cargo handles them, you must +use single quotes or double quotes around each glob pattern. +.sp +\fB\-\-lib\fR +.RS 4 +Document the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Document the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Document all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Document the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Document all example targets. +.RE +.sp +\fB\-\-test\fR \fIname\fR\[u2026] +.RS 4 +Document the specified integration test. This flag may be specified +multiple times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-tests\fR +.RS 4 +Document all targets that have the \fBtest = true\fR manifest +flag set. By default this includes the library and binaries built as +unittests, and integration tests. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +unittest, and once as a dependency for binaries, integration tests, etc.). +Targets may be enabled or disabled by setting the \fBtest\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-bench\fR \fIname\fR\[u2026] +.RS 4 +Document the specified benchmark. This flag may be specified multiple +times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-benches\fR +.RS 4 +Document all targets that have the \fBbench = true\fR +manifest flag set. By default this includes the library and binaries built +as benchmarks, and bench targets. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +benchmark, and once as a dependency for binaries, benchmarks, etc.). +Targets may be enabled or disabled by setting the \fBbench\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-all\-targets\fR +.RS 4 +Document all targets. This is equivalent to specifying \fB\-\-lib \-\-bins \-\-tests \-\-benches \-\-examples\fR\&. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Document for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Document optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Document with the given profile. +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\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. +.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 +.sp +\fB\-\-output\-format\fR +.RS 4 +The output type for the documentation emitted. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (default): Emit the documentation in HTML format. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit the documentation in the \fIexperimental JSON format\fR \&. +.RE +.sp +This option is only available on the \fInightly channel\fR +and requires the \fB\-Z unstable\-options\fR flag to enable. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Build documentation with custom CSS included from a given file: +.sp +.RS 4 +.nf +cargo rustdoc \-\-lib \-\- \-\-extend\-css extra.css +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-doc\fR(1), \fBrustdoc\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-search.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-search.1 new file mode 100644 index 000000000..a48c0397e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-search.1 @@ -0,0 +1,138 @@ +'\" t +.TH "CARGO\-SEARCH" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-search \[em] Search packages in the registry. Default registry is crates.io +.SH "SYNOPSIS" +\fBcargo search\fR [\fIoptions\fR] [\fIquery\fR\[u2026]] +.SH "DESCRIPTION" +This performs a textual search for crates on \&. The matching +crates will be displayed along with their description in TOML format suitable +for copying into a \fBCargo.toml\fR manifest. +.SH "OPTIONS" +.SS "Search Options" +.sp +\fB\-\-limit\fR \fIlimit\fR +.RS 4 +Limit the number of results (default: 10, max: 100). +.RE +.sp +\fB\-\-index\fR \fIindex\fR +.RS 4 +The URL of the registry index to use. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Search for a package from crates.io: +.sp +.RS 4 +.nf +cargo search serde +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-install\fR(1), \fBcargo\-publish\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-test.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-test.1 new file mode 100644 index 000000000..da783c1a3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-test.1 @@ -0,0 +1,624 @@ +'\" t +.TH "CARGO\-TEST" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-test \[em] Execute unit and integration tests of a package +.SH "SYNOPSIS" +\fBcargo test\fR [\fIoptions\fR] [\fItestname\fR] [\fB\-\-\fR \fItest\-options\fR] +.SH "DESCRIPTION" +Compile and execute unit, integration, and documentation tests. +.sp +The test filtering argument \fBTESTNAME\fR and all the arguments following the two +dashes (\fB\-\-\fR) are passed to the test binaries and thus to \fIlibtest\fR (rustc\[cq]s +built in unit\-test and micro\-benchmarking framework). If you\[cq]re passing +arguments to both Cargo and the binary, the ones after \fB\-\-\fR go to the binary, +the ones before go to Cargo. For details about libtest\[cq]s arguments see the +output of \fBcargo test \-\- \-\-help\fR and check out the rustc book\[cq]s chapter on +how tests work at \&. +.sp +As an example, this will filter for tests with \fBfoo\fR in their name and run them +on 3 threads in parallel: +.sp +.RS 4 +.nf +cargo test foo \-\- \-\-test\-threads 3 +.fi +.RE +.sp +Tests are built with the \fB\-\-test\fR option to \fBrustc\fR which creates a special +executable by linking your code with libtest. The executable automatically +runs all functions annotated with the \fB#[test]\fR attribute in multiple threads. +\fB#[bench]\fR annotated functions will also be run with one iteration to verify +that they are functional. +.sp +If the package contains multiple test targets, each target compiles to a +special executable as aforementioned, and then is run serially. +.sp +The libtest harness may be disabled by setting \fBharness = false\fR in the target +manifest settings, in which case your code will need to provide its own \fBmain\fR +function to handle running tests. +.SS "Documentation tests" +Documentation tests are also run by default, which is handled by \fBrustdoc\fR\&. It +extracts code samples from documentation comments of the library target, and +then executes them. +.sp +Different from normal test targets, each code block compiles to a doctest +executable on the fly with \fBrustc\fR\&. These executables run in parallel in +separate processes. The compilation of a code block is in fact a part of test +function controlled by libtest, so some options such as \fB\-\-jobs\fR might not +take effect. Note that this execution model of doctests is not guaranteed +and may change in the future; beware of depending on it. +.sp +See the \fIrustdoc book\fR for more information +on writing doc tests. +.SS "Working directory of tests" +The working directory when running each unit and integration test is set to the +root directory of the package the test belongs to. +Setting the working directory of tests to the package\[cq]s root directory makes it +possible for tests to reliably access the package\[cq]s files using relative paths, +regardless from where \fBcargo test\fR was executed from. +.sp +For documentation tests, the working directory when invoking \fBrustdoc\fR is set to +the workspace root directory, and is also the directory \fBrustdoc\fR uses as the +compilation directory of each documentation test. +The working directory when running each documentation test is set to the root +directory of the package the test belongs to, and is controlled via \fBrustdoc\fR\[cq]s +\fB\-\-test\-run\-directory\fR option. +.SH "OPTIONS" +.SS "Test Options" +.sp +\fB\-\-no\-run\fR +.RS 4 +Compile, but don\[cq]t run tests. +.RE +.sp +\fB\-\-no\-fail\-fast\fR +.RS 4 +Run all tests regardless of failure. Without this flag, Cargo will exit +after the first executable fails. The Rust test harness will run all tests +within the executable to completion, this flag only applies to the executable +as a whole. +.RE +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Test only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Test all members in the workspace. +.RE +.sp +\fB\-\-all\fR +.RS 4 +Deprecated alias for \fB\-\-workspace\fR\&. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Target Selection" +When no target selection options are given, \fBcargo test\fR will build the +following targets of the selected packages: +.sp +.RS 4 +\h'-04'\(bu\h'+03'lib \[em] used to link with binaries, examples, integration tests, and doc tests +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'bins (only if integration tests are built and required features are +available) +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'examples \[em] to ensure they compile +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'lib as a unit test +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'bins as unit tests +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'integration tests +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'doc tests for the lib target +.RE +.sp +The default behavior can be changed by setting the \fBtest\fR flag for the target +in the manifest settings. Setting examples to \fBtest = true\fR will build and run +the example as a test, replacing the example\[cq]s \fBmain\fR function with the +libtest harness. If you don\[cq]t want the \fBmain\fR function replaced, also include +\fBharness = false\fR, in which case the example will be built and executed as\-is. +.sp +Setting targets to \fBtest = false\fR will stop them from being tested by default. +Target selection options that take a target by name (such as \fB\-\-example foo\fR) +ignore the \fBtest\fR flag and will always test the given target. +.sp +Doc tests for libraries may be disabled by setting \fBdoctest = false\fR for the +library in the manifest. +.sp +See \fIConfiguring a target\fR +for more information on per\-target settings. +.sp +Binary targets are automatically built if there is an integration test or +benchmark being selected to test. This allows an integration +test to execute the binary to exercise and test its behavior. +The \fBCARGO_BIN_EXE_\fR +\fIenvironment variable\fR +is set when the integration test is built so that it can use the +\fI\f(BIenv\fI macro\fR to locate the +executable. +.sp +Passing target selection flags will test only the specified +targets. +.sp +Note that \fB\-\-bin\fR, \fB\-\-example\fR, \fB\-\-test\fR and \fB\-\-bench\fR flags also +support common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your +shell accidentally expanding glob patterns before Cargo handles them, you must +use single quotes or double quotes around each glob pattern. +.sp +\fB\-\-lib\fR +.RS 4 +Test the package\[cq]s library. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Test the specified binary. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-bins\fR +.RS 4 +Test all binary targets. +.RE +.sp +\fB\-\-example\fR \fIname\fR\[u2026] +.RS 4 +Test the specified example. This flag may be specified multiple times +and supports common Unix glob patterns. +.RE +.sp +\fB\-\-examples\fR +.RS 4 +Test all example targets. +.RE +.sp +\fB\-\-test\fR \fIname\fR\[u2026] +.RS 4 +Test the specified integration test. This flag may be specified +multiple times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-tests\fR +.RS 4 +Test all targets that have the \fBtest = true\fR manifest +flag set. By default this includes the library and binaries built as +unittests, and integration tests. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +unittest, and once as a dependency for binaries, integration tests, etc.). +Targets may be enabled or disabled by setting the \fBtest\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-bench\fR \fIname\fR\[u2026] +.RS 4 +Test the specified benchmark. This flag may be specified multiple +times and supports common Unix glob patterns. +.RE +.sp +\fB\-\-benches\fR +.RS 4 +Test all targets that have the \fBbench = true\fR +manifest flag set. By default this includes the library and binaries built +as benchmarks, and bench targets. Be aware that this will also build any +required dependencies, so the lib target may be built twice (once as a +benchmark, and once as a dependency for binaries, benchmarks, etc.). +Targets may be enabled or disabled by setting the \fBbench\fR flag in the +manifest settings for the target. +.RE +.sp +\fB\-\-all\-targets\fR +.RS 4 +Test all targets. This is equivalent to specifying \fB\-\-lib \-\-bins \-\-tests \-\-benches \-\-examples\fR\&. +.RE +.sp +\fB\-\-doc\fR +.RS 4 +Test only the library\[cq]s documentation. This cannot be mixed with other +target options. +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Compilation Options" +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Test for the given architecture. The default is the host architecture. The general format of the triple is +\fB\-\-\-\fR\&. Run \fBrustc \-\-print target\-list\fR for a +list of supported targets. This flag may be specified multiple times. +.sp +This may also be specified with the \fBbuild.target\fR +\fIconfig value\fR \&. +.sp +Note that specifying this flag makes Cargo run in a different mode where the +target artifacts are placed in a separate directory. See the +\fIbuild cache\fR documentation for more details. +.RE +.sp +\fB\-r\fR, +\fB\-\-release\fR +.RS 4 +Test optimized artifacts with the \fBrelease\fR profile. +See also the \fB\-\-profile\fR option for choosing a specific profile by name. +.RE +.sp +\fB\-\-profile\fR \fIname\fR +.RS 4 +Test with the given profile. +See \fIthe reference\fR for more details on profiles. +.RE +.sp +\fB\-\-timings=\fR\fIfmts\fR +.RS 4 +Output information how long each compilation takes, and track concurrency +information over time. Accepts an optional comma\-separated list of output +formats; \fB\-\-timings\fR without an argument will default to \fB\-\-timings=html\fR\&. +Specifying an output format (rather than the default) is unstable and requires +\fB\-Zunstable\-options\fR\&. Valid output formats: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhtml\fR (unstable, requires \fB\-Zunstable\-options\fR): Write a human\-readable file \fBcargo\-timing.html\fR to the +\fBtarget/cargo\-timings\fR directory with a report of the compilation. Also write +a report to the same directory with a timestamp in the filename if you want +to look at older runs. HTML output is suitable for human consumption only, +and does not provide machine\-readable timing data. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR (unstable, requires \fB\-Zunstable\-options\fR): Emit machine\-readable JSON +information about timing information. +.RE +.RE +.SS "Output Options" +.sp +\fB\-\-target\-dir\fR \fIdirectory\fR +.RS 4 +Directory for all generated artifacts and intermediate files. May also be +specified with the \fBCARGO_TARGET_DIR\fR environment variable, or the +\fBbuild.target\-dir\fR \fIconfig value\fR \&. +Defaults to \fBtarget\fR in the root of the workspace. +.RE +.SS "Display Options" +By default the Rust test harness hides output from test execution to keep +results readable. Test output can be recovered (e.g., for debugging) by passing +\fB\-\-nocapture\fR to the test binaries: +.sp +.RS 4 +.nf +cargo test \-\- \-\-nocapture +.fi +.RE +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The output format for diagnostic messages. Can be specified multiple times +and consists of comma\-separated values. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBhuman\fR (default): Display in a human\-readable text format. Conflicts with +\fBshort\fR and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBshort\fR: Emit shorter, human\-readable text messages. Conflicts with \fBhuman\fR +and \fBjson\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\fR: Emit JSON messages to stdout. See +\fIthe reference\fR +for more details. Conflicts with \fBhuman\fR and \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-short\fR: Ensure the \fBrendered\fR field of JSON messages contains +the \[lq]short\[rq] rendering from rustc. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-diagnostic\-rendered\-ansi\fR: Ensure the \fBrendered\fR field of JSON messages +contains embedded ANSI color codes for respecting rustc\[cq]s default color +scheme. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBjson\-render\-diagnostics\fR: Instruct Cargo to not include rustc diagnostics +in JSON messages printed, but instead Cargo itself should render the +JSON diagnostics coming from rustc. Cargo\[cq]s own JSON diagnostics and others +coming from rustc are still emitted. Cannot be used with \fBhuman\fR or \fBshort\fR\&. +.RE +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SS "Miscellaneous Options" +The \fB\-\-jobs\fR argument affects the building of the test executable but does not +affect how many threads are used when running the tests. The Rust test harness +includes an option to control the number of threads used: +.sp +.RS 4 +.nf +cargo test \-j 2 \-\- \-\-test\-threads=2 +.fi +.RE +.sp +\fB\-j\fR \fIN\fR, +\fB\-\-jobs\fR \fIN\fR +.RS 4 +Number of parallel jobs to run. May also be specified with the +\fBbuild.jobs\fR \fIconfig value\fR \&. Defaults to +the number of logical CPUs. If negative, it sets the maximum number of +parallel jobs to the number of logical CPUs plus provided value. If +a string \fBdefault\fR is provided, it sets the value back to defaults. +Should not be 0. +.RE +.sp +\fB\-\-future\-incompat\-report\fR +.RS 4 +Displays a future\-incompat report for any future\-incompatible warnings +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 for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Execute all the unit and integration tests of the current package: +.sp +.RS 4 +.nf +cargo test +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Run only tests whose names match against a filter string: +.sp +.RS 4 +.nf +cargo test name_filter +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Run only a specific test within a specific integration test: +.sp +.RS 4 +.nf +cargo test \-\-test int_test_name \-\- modname::test_name +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-bench\fR(1), \fItypes of tests\fR , \fIhow to write tests\fR diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-tree.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-tree.1 new file mode 100644 index 000000000..cd2739f9e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-tree.1 @@ -0,0 +1,534 @@ +'\" t +.TH "CARGO\-TREE" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-tree \[em] Display a tree visualization of a dependency graph +.SH "SYNOPSIS" +\fBcargo tree\fR [\fIoptions\fR] +.SH "DESCRIPTION" +This command will display a tree of dependencies to the terminal. An example +of a simple project that depends on the \[lq]rand\[rq] package: +.sp +.RS 4 +.nf +myproject v0.1.0 (/myproject) +`\-\- rand v0.7.3 + |\-\- getrandom v0.1.14 + | |\-\- cfg\-if v0.1.10 + | `\-\- libc v0.2.68 + |\-\- libc v0.2.68 (*) + |\-\- rand_chacha v0.2.2 + | |\-\- ppv\-lite86 v0.2.6 + | `\-\- rand_core v0.5.1 + | `\-\- getrandom v0.1.14 (*) + `\-\- rand_core v0.5.1 (*) +[build\-dependencies] +`\-\- cc v1.0.50 +.fi +.RE +.sp +Packages marked with \fB(*)\fR have been \[lq]de\-duplicated\[rq]\&. The dependencies for the +package have already been shown elsewhere in the graph, and so are not +repeated. Use the \fB\-\-no\-dedupe\fR option to repeat the duplicates. +.sp +The \fB\-e\fR flag can be used to select the dependency kinds to display. The +\[lq]features\[rq] kind changes the output to display the features enabled by +each dependency. For example, \fBcargo tree \-e features\fR: +.sp +.RS 4 +.nf +myproject v0.1.0 (/myproject) +`\-\- log feature "serde" + `\-\- log v0.4.8 + |\-\- serde v1.0.106 + `\-\- cfg\-if feature "default" + `\-\- cfg\-if v0.1.10 +.fi +.RE +.sp +In this tree, \fBmyproject\fR depends on \fBlog\fR with the \fBserde\fR feature. \fBlog\fR in +turn depends on \fBcfg\-if\fR with \[lq]default\[rq] features. When using \fB\-e features\fR it +can be helpful to use \fB\-i\fR flag to show how the features flow into a package. +See the examples below for more detail. +.SS "Feature Unification" +This command shows a graph much closer to a feature\-unified graph Cargo will +build, rather than what you list in \fBCargo.toml\fR\&. For instance, if you specify +the same dependency in both \fB[dependencies]\fR and \fB[dev\-dependencies]\fR but with +different features on. This command may merge all features and show a \fB(*)\fR on +one of the dependency to indicate the duplicate. +.sp +As a result, for a mostly equivalent overview of what \fBcargo build\fR does, +\fBcargo tree \-e normal,build\fR is pretty close; for a mostly equivalent overview +of what \fBcargo test\fR does, \fBcargo tree\fR is pretty close. However, it doesn\[cq]t +guarantee the exact equivalence to what Cargo is going to build, since a +compilation is complex and depends on lots of different factors. +.sp +To learn more about feature unification, check out this +\fIdedicated section\fR \&. +.SH "OPTIONS" +.SS "Tree Options" +.sp +\fB\-i\fR \fIspec\fR, +\fB\-\-invert\fR \fIspec\fR +.RS 4 +Show the reverse dependencies for the given package. This flag will invert +the tree and display the packages that depend on the given package. +.sp +Note that in a workspace, by default it will only display the package\[cq]s +reverse dependencies inside the tree of the workspace member in the current +directory. The \fB\-\-workspace\fR flag can be used to extend it so that it will +show the package\[cq]s reverse dependencies across the entire workspace. The \fB\-p\fR +flag can be used to display the package\[cq]s reverse dependencies only with the +subtree of the package given to \fB\-p\fR\&. +.RE +.sp +\fB\-\-prune\fR \fIspec\fR +.RS 4 +Prune the given package from the display of the dependency tree. +.RE +.sp +\fB\-\-depth\fR \fIdepth\fR +.RS 4 +Maximum display depth of the dependency tree. A depth of 1 displays the direct +dependencies, for example. +.sp +If the given value is \fBworkspace\fR, only shows the dependencies that are member +of the current workspace, instead. +.RE +.sp +\fB\-\-no\-dedupe\fR +.RS 4 +Do not de\-duplicate repeated dependencies. Usually, when a package has already +displayed its dependencies, further occurrences will not re\-display its +dependencies, and will include a \fB(*)\fR to indicate it has already been shown. +This flag will cause those duplicates to be repeated. +.RE +.sp +\fB\-d\fR, +\fB\-\-duplicates\fR +.RS 4 +Show only dependencies which come in multiple versions (implies \fB\-\-invert\fR). +When used with the \fB\-p\fR flag, only shows duplicates within the subtree of the +given package. +.sp +It can be beneficial for build times and executable sizes to avoid building +that same package multiple times. This flag can help identify the offending +packages. You can then investigate if the package that depends on the +duplicate with the older version can be updated to the newer version so that +only one instance is built. +.RE +.sp +\fB\-e\fR \fIkinds\fR, +\fB\-\-edges\fR \fIkinds\fR +.RS 4 +The dependency kinds to display. Takes a comma separated list of values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBall\fR \[em] Show all edge kinds. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnormal\fR \[em] Show normal dependencies. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBbuild\fR \[em] Show build dependencies. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBdev\fR \[em] Show development dependencies. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBfeatures\fR \[em] Show features enabled by each dependency. If this is the only +kind given, then it will automatically include the other dependency kinds. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBno\-normal\fR \[em] Do not include normal dependencies. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBno\-build\fR \[em] Do not include build dependencies. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBno\-dev\fR \[em] Do not include development dependencies. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBno\-proc\-macro\fR \[em] Do not include procedural macro dependencies. +.RE +.sp +The \fBnormal\fR, \fBbuild\fR, \fBdev\fR, and \fBall\fR dependency kinds cannot be mixed with +\fBno\-normal\fR, \fBno\-build\fR, or \fBno\-dev\fR dependency kinds. +.sp +The default is \fBnormal,build,dev\fR\&. +.RE +.sp +\fB\-\-target\fR \fItriple\fR +.RS 4 +Filter dependencies matching the given \fItarget triple\fR \&. +The default is the host platform. Use the value \fBall\fR to include \fIall\fR targets. +.RE +.SS "Tree Formatting Options" +.sp +\fB\-\-charset\fR \fIcharset\fR +.RS 4 +Chooses the character set to use for the tree. Valid values are \[lq]utf8\[rq] or +\[lq]ascii\[rq]\&. When unspecified, cargo will auto\-select a value. +.RE +.sp +\fB\-f\fR \fIformat\fR, +\fB\-\-format\fR \fIformat\fR +.RS 4 +Set the format string for each package. The default is \[lq]{p}\[rq]\&. +.sp +This is an arbitrary string which will be used to display each package. The following +strings will be replaced with the corresponding value: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB{p}\fR \[em] The package name. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB{l}\fR \[em] The package license. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB{r}\fR \[em] The package repository URL. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB{f}\fR \[em] Comma\-separated list of package features that are enabled. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB{lib}\fR \[em] The name, as used in a \fBuse\fR statement, of the package\[cq]s library. +.RE +.RE +.sp +\fB\-\-prefix\fR \fIprefix\fR +.RS 4 +Sets how each line is displayed. The \fIprefix\fR value can be one of: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBindent\fR (default) \[em] Shows each line indented as a tree. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBdepth\fR \[em] Show as a list, with the numeric depth printed before each entry. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnone\fR \[em] Show as a flat list. +.RE +.RE +.SS "Package Selection" +By default, when no package selection options are given, the packages selected +depend on the selected manifest file (based on the current working directory if +\fB\-\-manifest\-path\fR is not given). If the manifest is the root of a workspace then +the workspaces default members are selected, otherwise only the package defined +by the manifest will be selected. +.sp +The default members of a workspace can be set explicitly with the +\fBworkspace.default\-members\fR key in the root manifest. If this is not set, a +virtual workspace will include all workspace members (equivalent to passing +\fB\-\-workspace\fR), and a non\-virtual workspace will include only the root crate itself. +.sp +\fB\-p\fR \fIspec\fR\[u2026], +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Display only the specified packages. See \fBcargo\-pkgid\fR(1) for the +SPEC format. This flag may be specified multiple times and supports common Unix +glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell accidentally +expanding glob patterns before Cargo handles them, you must use single quotes or +double quotes around each pattern. +.RE +.sp +\fB\-\-workspace\fR +.RS 4 +Display all members in the workspace. +.RE +.sp +\fB\-\-exclude\fR \fISPEC\fR\[u2026] +.RS 4 +Exclude the specified packages. Must be used in conjunction with the +\fB\-\-workspace\fR flag. This flag may be specified multiple times and supports +common Unix glob patterns like \fB*\fR, \fB?\fR and \fB[]\fR\&. However, to avoid your shell +accidentally expanding glob patterns before Cargo handles them, you must use +single quotes or double quotes around each pattern. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Feature Selection" +The feature flags allow you to control which features are enabled. When no +feature options are given, the \fBdefault\fR feature is activated for every +selected package. +.sp +See \fIthe features documentation\fR +for more details. +.sp +\fB\-F\fR \fIfeatures\fR, +\fB\-\-features\fR \fIfeatures\fR +.RS 4 +Space or comma separated list of features to activate. Features of workspace +members may be enabled with \fBpackage\-name/feature\-name\fR syntax. This flag may +be specified multiple times, which enables all specified features. +.RE +.sp +\fB\-\-all\-features\fR +.RS 4 +Activate all available features of all selected packages. +.RE +.sp +\fB\-\-no\-default\-features\fR +.RS 4 +Do not activate the \fBdefault\fR feature of the selected packages. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Display the tree for the package in the current directory: +.sp +.RS 4 +.nf +cargo tree +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Display all the packages that depend on the \fBsyn\fR package: +.sp +.RS 4 +.nf +cargo tree \-i syn +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Show the features enabled on each package: +.sp +.RS 4 +.nf +cargo tree \-\-format "{p} {f}" +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 4.\h'+01'Show all packages that are built multiple times. This can happen if multiple +semver\-incompatible versions appear in the tree (like 1.0.0 and 2.0.0). +.sp +.RS 4 +.nf +cargo tree \-d +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 5.\h'+01'Explain why features are enabled for the \fBsyn\fR package: +.sp +.RS 4 +.nf +cargo tree \-e features \-i syn +.fi +.RE +.sp +The \fB\-e features\fR flag is used to show features. The \fB\-i\fR flag is used to +invert the graph so that it displays the packages that depend on \fBsyn\fR\&. An +example of what this would display: +.sp +.RS 4 +.nf +syn v1.0.17 +|\-\- syn feature "clone\-impls" +| `\-\- syn feature "default" +| `\-\- rustversion v1.0.2 +| `\-\- rustversion feature "default" +| `\-\- myproject v0.1.0 (/myproject) +| `\-\- myproject feature "default" (command\-line) +|\-\- syn feature "default" (*) +|\-\- syn feature "derive" +| `\-\- syn feature "default" (*) +|\-\- syn feature "full" +| `\-\- rustversion v1.0.2 (*) +|\-\- syn feature "parsing" +| `\-\- syn feature "default" (*) +|\-\- syn feature "printing" +| `\-\- syn feature "default" (*) +|\-\- syn feature "proc\-macro" +| `\-\- syn feature "default" (*) +`\-\- syn feature "quote" + |\-\- syn feature "printing" (*) + `\-\- syn feature "proc\-macro" (*) +.fi +.RE +.sp +To read this graph, you can follow the chain for each feature from the root +to see why it is included. For example, the \[lq]full\[rq] feature is added by the +\fBrustversion\fR crate which is included from \fBmyproject\fR (with the default +features), and \fBmyproject\fR is the package selected on the command\-line. All +of the other \fBsyn\fR features are added by the \[lq]default\[rq] feature (\[lq]quote\[rq] is +added by \[lq]printing\[rq] and \[lq]proc\-macro\[rq], both of which are default features). +.sp +If you\[cq]re having difficulty cross\-referencing the de\-duplicated \fB(*)\fR +entries, try with the \fB\-\-no\-dedupe\fR flag to get the full output. +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-metadata\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-uninstall.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-uninstall.1 new file mode 100644 index 000000000..141410235 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-uninstall.1 @@ -0,0 +1,161 @@ +'\" t +.TH "CARGO\-UNINSTALL" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-uninstall \[em] Remove a Rust binary +.SH "SYNOPSIS" +\fBcargo uninstall\fR [\fIoptions\fR] [\fIspec\fR\[u2026]] +.SH "DESCRIPTION" +This command removes a package installed with \fBcargo\-install\fR(1). The \fIspec\fR +argument is a package ID specification of the package to remove (see +\fBcargo\-pkgid\fR(1)). +.sp +By default all binaries are removed for a crate but the \fB\-\-bin\fR and +\fB\-\-example\fR flags can be used to only remove particular binaries. +.sp +The installation root is determined, in order of precedence: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB\-\-root\fR option +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBCARGO_INSTALL_ROOT\fR environment variable +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBinstall.root\fR Cargo \fIconfig value\fR +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBCARGO_HOME\fR environment variable +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB$HOME/.cargo\fR +.RE +.SH "OPTIONS" +.SS "Uninstall Options" +.sp +\fB\-p\fR, +\fB\-\-package\fR \fIspec\fR\[u2026] +.RS 4 +Package to uninstall. +.RE +.sp +\fB\-\-bin\fR \fIname\fR\[u2026] +.RS 4 +Only uninstall the binary \fIname\fR\&. +.RE +.sp +\fB\-\-root\fR \fIdir\fR +.RS 4 +Directory to uninstall packages from. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Uninstall a previously installed package. +.sp +.RS 4 +.nf +cargo uninstall ripgrep +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-install\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-update.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-update.1 new file mode 100644 index 000000000..6b8c6c7c1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-update.1 @@ -0,0 +1,283 @@ +'\" t +.TH "CARGO\-UPDATE" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-update \[em] Update dependencies as recorded in the local lock file +.SH "SYNOPSIS" +\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 +latest available versions. +.SH "OPTIONS" +.SS "Update Options" +.sp +\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 \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 \fIspec\fR is not specified, all dependencies are updated. +.RE +.sp +\fB\-\-recursive\fR +.RS 4 +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 \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). +.sp +While not recommended, you can specify a yanked version of a package. +When possible, try other non\-yanked SemVer\-compatible versions or seek help +from the maintainers of the package. +.sp +A compatible \fBpre\-release\fR version can also be specified even when the version +requirement in \fBCargo.toml\fR doesn\[cq]t contain any pre\-release identifier (nightly only). +.RE +.sp +\fB\-\-breaking\fR \fIdirectory\fR +.RS 4 +Update \fIspec\fR to latest SemVer\-breaking version. +.sp +Version requirements will be modified to allow this update. +.sp +This only applies to dependencies when +.sp +.RS 4 +\h'-04'\(bu\h'+03'The package is a dependency of a workspace member +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'The dependency is not renamed +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'A SemVer\-incompatible version is available +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'The \[lq]SemVer operator\[rq] is used (\fB^\fR which is the default) +.RE +.sp +This option is unstable and available only on the +\fInightly channel\fR +and requires the \fB\-Z unstable\-options\fR flag to enable. +See for more information. +.RE +.sp +\fB\-w\fR, +\fB\-\-workspace\fR +.RS 4 +Attempt to update only packages defined in the workspace. Other packages +are updated only if they don\[cq]t already exist in the lockfile. This +option is useful for updating \fBCargo.lock\fR after you\[cq]ve changed version +numbers in \fBCargo.toml\fR\&. +.RE +.sp +\fB\-\-dry\-run\fR +.RS 4 +Displays what would be updated, but doesn\[cq]t actually write the lockfile. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-ignore\-rust\-version\fR +.RS 4 +Ignore \fBrust\-version\fR specification in packages. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Update all dependencies in the lockfile: +.sp +.RS 4 +.nf +cargo update +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Update only specific dependencies: +.sp +.RS 4 +.nf +cargo update foo bar +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Set a specific dependency to a specific version: +.sp +.RS 4 +.nf +cargo update foo \-\-precise 1.2.3 +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-generate\-lockfile\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-vendor.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-vendor.1 new file mode 100644 index 000000000..4a52bad55 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-vendor.1 @@ -0,0 +1,251 @@ +'\" t +.TH "CARGO\-VENDOR" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-vendor \[em] Vendor all dependencies locally +.SH "SYNOPSIS" +\fBcargo vendor\fR [\fIoptions\fR] [\fIpath\fR] +.SH "DESCRIPTION" +This cargo subcommand will vendor all crates.io and git dependencies for a +project into the specified directory at \fB\fR\&. After this command completes +the vendor directory specified by \fB\fR will contain all remote sources from +dependencies specified. Additional manifests beyond the default one can be +specified with the \fB\-s\fR option. +.sp +The configuration necessary to use the vendored sources would be printed to +stdout after \fBcargo vendor\fR completes the vendoring process. +You will need to add or redirect it to your Cargo configuration file, +which is usually \fB\&.cargo/config.toml\fR locally for the current package. +.sp +Cargo treats vendored sources as read\-only as it does to registry and git sources. +If you intend to modify a crate from a remote source, +use \fB[patch]\fR or a \fBpath\fR dependency pointing to a local copy of that crate. +Cargo will then correctly handle the crate on incremental rebuilds, +as it knows that it is no longer a read\-only dependency. +.SH "OPTIONS" +.SS "Vendor Options" +.sp +\fB\-s\fR \fImanifest\fR, +\fB\-\-sync\fR \fImanifest\fR +.RS 4 +Specify an extra \fBCargo.toml\fR manifest to workspaces which should also be +vendored and synced to the output. May be specified multiple times. +.RE +.sp +\fB\-\-no\-delete\fR +.RS 4 +Don\[cq]t delete the \[lq]vendor\[rq] directory when vendoring, but rather keep all +existing contents of the vendor directory +.RE +.sp +\fB\-\-respect\-source\-config\fR +.RS 4 +Instead of ignoring \fB[source]\fR configuration by default in \fB\&.cargo/config.toml\fR +read it and use it when downloading crates from crates.io, for example +.RE +.sp +\fB\-\-versioned\-dirs\fR +.RS 4 +Normally versions are only added to disambiguate multiple versions of the +same package. This option causes all directories in the \[lq]vendor\[rq] directory +to be versioned, which makes it easier to track the history of vendored +packages over time, and can help with the performance of re\-vendoring when +only a subset of the packages have changed. +.RE +.SS "Manifest Options" +.sp +\fB\-\-manifest\-path\fR \fIpath\fR +.RS 4 +Path to the \fBCargo.toml\fR file. By default, Cargo searches for the +\fBCargo.toml\fR file in the current directory or any parent directory. +.RE +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.sp +\fB\-\-lockfile\-path\fR \fIPATH\fR +.RS 4 +Changes the path of the lockfile from the default (\fB/Cargo.lock\fR) to \fIPATH\fR\&. \fIPATH\fR must end with +\fBCargo.lock\fR (e.g. \fB\-\-lockfile\-path /tmp/temporary\-lockfile/Cargo.lock\fR). Note that providing +\fB\-\-lockfile\-path\fR will ignore existing lockfile at the default path, and instead will +either use the lockfile from \fIPATH\fR, or write a new lockfile into the provided \fIPATH\fR if it doesn\[cq]t exist. +This flag can be used to run most commands in read\-only directories, writing lockfile into the provided \fIPATH\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#14421\fR ). +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Vendor all dependencies into a local \[lq]vendor\[rq] folder +.sp +.RS 4 +.nf +cargo vendor +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Vendor all dependencies into a local \[lq]third\-party/vendor\[rq] folder +.sp +.RS 4 +.nf +cargo vendor third\-party/vendor +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Vendor the current workspace as well as another to \[lq]vendor\[rq] +.sp +.RS 4 +.nf +cargo vendor \-s ../path/to/Cargo.toml +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 4.\h'+01'Vendor and redirect the necessary vendor configs to a config file. +.sp +.RS 4 +.nf +cargo vendor > path/to/my/cargo/config.toml +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-version.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-version.1 new file mode 100644 index 000000000..6f1f46303 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-version.1 @@ -0,0 +1,52 @@ +'\" t +.TH "CARGO\-VERSION" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-version \[em] Show version information +.SH "SYNOPSIS" +\fBcargo version\fR [\fIoptions\fR] +.SH "DESCRIPTION" +Displays the version of Cargo. +.SH "OPTIONS" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Display additional version information. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Display the version: +.sp +.RS 4 +.nf +cargo version +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'The version is also available via flags: +.sp +.RS 4 +.nf +cargo \-\-version +cargo \-V +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Display extra version information: +.sp +.RS 4 +.nf +cargo \-Vv +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-yank.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-yank.1 new file mode 100644 index 000000000..7d6809747 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo-yank.1 @@ -0,0 +1,248 @@ +'\" t +.TH "CARGO\-YANK" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo\-yank \[em] Remove a pushed crate from the index +.SH "SYNOPSIS" +\fBcargo yank\fR [\fIoptions\fR] \fIcrate\fR@\fIversion\fR +.br +\fBcargo yank\fR [\fIoptions\fR] \fB\-\-version\fR \fIversion\fR [\fIcrate\fR] +.SH "DESCRIPTION" +The yank command removes a previously published crate\[cq]s version from the +server\[cq]s index. This command does not delete any data, and the crate will +still be available for download via the registry\[cq]s download link. +.sp +Cargo will not use a yanked version for any new project or checkout without a +pre\-existing lockfile, and will generate an error if there are no longer +any compatible versions for your crate. +.sp +This command requires you to be authenticated with either the \fB\-\-token\fR option +or using \fBcargo\-login\fR(1). +.sp +If the crate name is not specified, it will use the package name from the +current directory. +.SS "How yank works" +For example, the \fBfoo\fR crate published version \fB1.5.0\fR and another crate \fBbar\fR +declared a dependency on version \fBfoo = "1.5"\fR\&. Now \fBfoo\fR releases a new, but +not semver compatible, version \fB2.0.0\fR, and finds a critical issue with \fB1.5.0\fR\&. +If \fB1.5.0\fR is yanked, no new project or checkout without an existing lockfile +will be able to use crate \fBbar\fR as it relies on \fB1.5\fR\&. +.sp +In this case, the maintainers of \fBfoo\fR should first publish a semver compatible +version such as \fB1.5.1\fR prior to yanking \fB1.5.0\fR so that \fBbar\fR and all projects +that depend on \fBbar\fR will continue to work. +.sp +As another example, consider a crate \fBbar\fR with published versions \fB1.5.0\fR, +\fB1.5.1\fR, \fB1.5.2\fR, \fB2.0.0\fR and \fB3.0.0\fR\&. The following table identifies the +versions cargo could use in the absence of a lockfile for different SemVer +requirements, following a given release being yanked: + +.TS +allbox tab(:); +lt lt lt lt. +T{ +Yanked Version / SemVer requirement +T}:T{ +\fBbar = "1.5.0"\fR +T}:T{ +\fBbar = "=1.5.0"\fR +T}:T{ +\fBbar = "2.0.0"\fR +T} +T{ +\fB1.5.0\fR +T}:T{ +Use either \fB1.5.1\fR or \fB1.5.2\fR +T}:T{ +\fBReturn Error\fR +T}:T{ +Use \fB2.0.0\fR +T} +T{ +\fB1.5.1\fR +T}:T{ +Use either \fB1.5.0\fR or \fB1.5.2\fR +T}:T{ +Use \fB1.5.0\fR +T}:T{ +Use \fB2.0.0\fR +T} +T{ +\fB2.0.0\fR +T}:T{ +Use either \fB1.5.0\fR, \fB1.5.1\fR or \fB1.5.2\fR +T}:T{ +Use \fB1.5.0\fR +T}:T{ +\fBReturn Error\fR +T} +.TE +.sp +.SS "When to yank" +Crates should only be yanked in exceptional circumstances, for example, an +accidental publish, an unintentional SemVer breakages, or a significantly +broken and unusable crate. In the case of security vulnerabilities, \fIRustSec\fR +is typically a less disruptive mechanism to inform users and encourage them +to upgrade, and avoids the possibility of significant downstream disruption +irrespective of susceptibility to the vulnerability in question. +.sp +A common workflow is to yank a crate having already published a semver +compatible version, to reduce the probability of preventing dependent +crates from compiling. +.sp +When addressing copyright, licensing, or personal data issues with a published +crate, simply yanking it may not suffice. In such cases, contact the maintainers +of the registry you used. For crates.io, refer to their \fIpolicies\fR and contact +them at \&. +.sp +If credentials have been leaked, the recommended course of action is to revoke +them immediately. Once a crate has been published, it is impossible to determine +if the leaked credentials have been copied. Yanking the crate only prevents new +users from downloading it, but cannot stop those who have already downloaded it +from keeping or even spreading the leaked credentials. +.SH "OPTIONS" +.SS "Yank Options" +.sp +\fB\-\-vers\fR \fIversion\fR, +\fB\-\-version\fR \fIversion\fR +.RS 4 +The version to yank or un\-yank. +.RE +.sp +\fB\-\-undo\fR +.RS 4 +Undo a yank, putting a version back into the index. +.RE +.sp +\fB\-\-token\fR \fItoken\fR +.RS 4 +API token to use when authenticating. This overrides the token stored in +the credentials file (which is created by \fBcargo\-login\fR(1)). +.sp +\fICargo config\fR environment variables can be +used to override the tokens stored in the credentials file. The token for +crates.io may be specified with the \fBCARGO_REGISTRY_TOKEN\fR environment +variable. Tokens for other registries may be specified with environment +variables of the form \fBCARGO_REGISTRIES_NAME_TOKEN\fR where \fBNAME\fR is the name +of the registry in all capital letters. +.RE +.sp +\fB\-\-index\fR \fIindex\fR +.RS 4 +The URL of the registry index to use. +.RE +.sp +\fB\-\-registry\fR \fIregistry\fR +.RS 4 +Name of the registry to use. Registry names are defined in \fICargo config +files\fR \&. If not specified, the default registry is used, +which is defined by the \fBregistry.default\fR config key which defaults to +\fBcrates\-io\fR\&. +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Yank a crate from the index: +.sp +.RS 4 +.nf +cargo yank foo@1.0.7 +.fi +.RE +.RE +.SH "SEE ALSO" +\fBcargo\fR(1), \fBcargo\-login\fR(1), \fBcargo\-publish\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo.1 b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo.1 new file mode 100644 index 000000000..80c8682a6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/etc/man/cargo.1 @@ -0,0 +1,414 @@ +'\" t +.TH "CARGO" "1" +.nh +.ad l +.ss \n[.ss] 0 +.SH "NAME" +cargo \[em] The Rust package manager +.SH "SYNOPSIS" +\fBcargo\fR [\fIoptions\fR] \fIcommand\fR [\fIargs\fR] +.br +\fBcargo\fR [\fIoptions\fR] \fB\-\-version\fR +.br +\fBcargo\fR [\fIoptions\fR] \fB\-\-list\fR +.br +\fBcargo\fR [\fIoptions\fR] \fB\-\-help\fR +.br +\fBcargo\fR [\fIoptions\fR] \fB\-\-explain\fR \fIcode\fR +.SH "DESCRIPTION" +This program is a package manager and build tool for the Rust language, +available at \&. +.SH "COMMANDS" +.SS "Build Commands" +\fBcargo\-bench\fR(1) +.br +\ \ \ \ Execute benchmarks of a package. +.sp +\fBcargo\-build\fR(1) +.br +\ \ \ \ Compile a package. +.sp +\fBcargo\-check\fR(1) +.br +\ \ \ \ Check a local package and all of its dependencies for errors. +.sp +\fBcargo\-clean\fR(1) +.br +\ \ \ \ Remove artifacts that Cargo has generated in the past. +.sp +\fBcargo\-doc\fR(1) +.br +\ \ \ \ Build a package\[cq]s documentation. +.sp +\fBcargo\-fetch\fR(1) +.br +\ \ \ \ Fetch dependencies of a package from the network. +.sp +\fBcargo\-fix\fR(1) +.br +\ \ \ \ Automatically fix lint warnings reported by rustc. +.sp +\fBcargo\-run\fR(1) +.br +\ \ \ \ Run a binary or example of the local package. +.sp +\fBcargo\-rustc\fR(1) +.br +\ \ \ \ Compile a package, and pass extra options to the compiler. +.sp +\fBcargo\-rustdoc\fR(1) +.br +\ \ \ \ Build a package\[cq]s documentation, using specified custom flags. +.sp +\fBcargo\-test\fR(1) +.br +\ \ \ \ Execute unit and integration tests of a package. +.SS "Manifest Commands" +\fBcargo\-add\fR(1) +.br +\ \ \ \ Add dependencies to a \fBCargo.toml\fR manifest file. +.sp +\fBcargo\-generate\-lockfile\fR(1) +.br +\ \ \ \ Generate \fBCargo.lock\fR for a project. +.sp +\fBcargo\-info\fR(1) +.br +\ \ \ \ Display information about a package in the registry. Default registry is crates.io. +.sp +\fBcargo\-locate\-project\fR(1) +.br +\ \ \ \ Print a JSON representation of a \fBCargo.toml\fR file\[cq]s location. +.sp +\fBcargo\-metadata\fR(1) +.br +\ \ \ \ Output the resolved dependencies of a package in machine\-readable format. +.sp +\fBcargo\-pkgid\fR(1) +.br +\ \ \ \ Print a fully qualified package specification. +.sp +\fBcargo\-remove\fR(1) +.br +\ \ \ \ Remove dependencies from a \fBCargo.toml\fR manifest file. +.sp +\fBcargo\-tree\fR(1) +.br +\ \ \ \ Display a tree visualization of a dependency graph. +.sp +\fBcargo\-update\fR(1) +.br +\ \ \ \ Update dependencies as recorded in the local lock file. +.sp +\fBcargo\-vendor\fR(1) +.br +\ \ \ \ Vendor all dependencies locally. +.SS "Package Commands" +\fBcargo\-init\fR(1) +.br +\ \ \ \ Create a new Cargo package in an existing directory. +.sp +\fBcargo\-install\fR(1) +.br +\ \ \ \ Build and install a Rust binary. +.sp +\fBcargo\-new\fR(1) +.br +\ \ \ \ Create a new Cargo package. +.sp +\fBcargo\-search\fR(1) +.br +\ \ \ \ Search packages in crates.io. +.sp +\fBcargo\-uninstall\fR(1) +.br +\ \ \ \ Remove a Rust binary. +.SS "Publishing Commands" +\fBcargo\-login\fR(1) +.br +\ \ \ \ Save an API token from the registry locally. +.sp +\fBcargo\-logout\fR(1) +.br +\ \ \ \ Remove an API token from the registry locally. +.sp +\fBcargo\-owner\fR(1) +.br +\ \ \ \ Manage the owners of a crate on the registry. +.sp +\fBcargo\-package\fR(1) +.br +\ \ \ \ Assemble the local package into a distributable tarball. +.sp +\fBcargo\-publish\fR(1) +.br +\ \ \ \ Upload a package to the registry. +.sp +\fBcargo\-yank\fR(1) +.br +\ \ \ \ Remove a pushed crate from the index. +.SS "General Commands" +\fBcargo\-help\fR(1) +.br +\ \ \ \ Display help information about Cargo. +.sp +\fBcargo\-version\fR(1) +.br +\ \ \ \ Show version information. +.SH "OPTIONS" +.SS "Special Options" +.sp +\fB\-V\fR, +\fB\-\-version\fR +.RS 4 +Print version info and exit. If used with \fB\-\-verbose\fR, prints extra +information. +.RE +.sp +\fB\-\-list\fR +.RS 4 +List all installed Cargo subcommands. If used with \fB\-\-verbose\fR, prints extra +information. +.RE +.sp +\fB\-\-explain\fR \fIcode\fR +.RS 4 +Run \fBrustc \-\-explain CODE\fR which will print out a detailed explanation of an +error message (for example, \fBE0004\fR). +.RE +.SS "Display Options" +.sp +\fB\-v\fR, +\fB\-\-verbose\fR +.RS 4 +Use verbose output. May be specified twice for \[lq]very verbose\[rq] output which +includes extra output such as dependency warnings and build script output. +May also be specified with the \fBterm.verbose\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-q\fR, +\fB\-\-quiet\fR +.RS 4 +Do not print cargo log messages. +May also be specified with the \fBterm.quiet\fR +\fIconfig value\fR \&. +.RE +.sp +\fB\-\-color\fR \fIwhen\fR +.RS 4 +Control when colored output is used. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBauto\fR (default): Automatically detect if color support is available on the +terminal. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBalways\fR: Always display colors. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fBnever\fR: Never display colors. +.RE +.sp +May also be specified with the \fBterm.color\fR +\fIconfig value\fR \&. +.RE +.SS "Manifest Options" +.sp +\fB\-\-locked\fR +.RS 4 +Asserts that the exact same dependencies and versions are used as when the +existing \fBCargo.lock\fR file was originally generated. Cargo will exit with an +error when either of the following scenarios arises: +.sp +.RS 4 +\h'-04'\(bu\h'+03'The lock file is missing. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'Cargo attempted to change the lock file due to a different dependency resolution. +.RE +.sp +It may be used in environments where deterministic builds are desired, +such as in CI pipelines. +.RE +.sp +\fB\-\-offline\fR +.RS 4 +Prevents Cargo from accessing the network for any reason. Without this +flag, Cargo will stop with an error if it needs to access the network and +the network is not available. With this flag, Cargo will attempt to +proceed without the network if possible. +.sp +Beware that this may result in different dependency resolution than online +mode. Cargo will restrict itself to crates that are downloaded locally, even +if there might be a newer version as indicated in the local copy of the index. +See the \fBcargo\-fetch\fR(1) command to download dependencies before going +offline. +.sp +May also be specified with the \fBnet.offline\fR \fIconfig value\fR \&. +.RE +.sp +\fB\-\-frozen\fR +.RS 4 +Equivalent to specifying both \fB\-\-locked\fR and \fB\-\-offline\fR\&. +.RE +.SS "Common Options" +.sp +\fB+\fR\fItoolchain\fR +.RS 4 +If Cargo has been installed with rustup, and the first argument to \fBcargo\fR +begins with \fB+\fR, it will be interpreted as a rustup toolchain name (such +as \fB+stable\fR or \fB+nightly\fR). +See the \fIrustup documentation\fR +for more information about how toolchain overrides work. +.RE +.sp +\fB\-\-config\fR \fIKEY=VALUE\fR or \fIPATH\fR +.RS 4 +Overrides a Cargo configuration value. The argument should be in TOML syntax of \fBKEY=VALUE\fR, +or provided as a path to an extra configuration file. This flag may be specified multiple times. +See the \fIcommand\-line overrides section\fR for more information. +.RE +.sp +\fB\-C\fR \fIPATH\fR +.RS 4 +Changes the current working directory before executing any specified operations. This affects +things like where cargo looks by default for the project manifest (\fBCargo.toml\fR), as well as +the directories searched for discovering \fB\&.cargo/config.toml\fR, for example. This option must +appear before the command name, for example \fBcargo \-C path/to/my\-project build\fR\&. +.sp +This option is only available on the \fInightly +channel\fR and +requires the \fB\-Z unstable\-options\fR flag to enable (see +\fI#10098\fR ). +.RE +.sp +\fB\-h\fR, +\fB\-\-help\fR +.RS 4 +Prints help information. +.RE +.sp +\fB\-Z\fR \fIflag\fR +.RS 4 +Unstable (nightly\-only) flags to Cargo. Run \fBcargo \-Z help\fR for details. +.RE +.SH "ENVIRONMENT" +See \fIthe reference\fR for +details on environment variables that Cargo reads. +.SH "EXIT STATUS" +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB0\fR: Cargo succeeded. +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+03'\fB101\fR: Cargo failed to complete. +.RE +.SH "FILES" +\fB~/.cargo/\fR +.br +\ \ \ \ Default location for Cargo\[cq]s \[lq]home\[rq] directory where it +stores various files. The location can be changed with the \fBCARGO_HOME\fR +environment variable. +.sp +\fB$CARGO_HOME/bin/\fR +.br +\ \ \ \ Binaries installed by \fBcargo\-install\fR(1) will be located here. If using +\fIrustup\fR , executables distributed with Rust are also located here. +.sp +\fB$CARGO_HOME/config.toml\fR +.br +\ \ \ \ The global configuration file. See \fIthe reference\fR +for more information about configuration files. +.sp +\fB\&.cargo/config.toml\fR +.br +\ \ \ \ Cargo automatically searches for a file named \fB\&.cargo/config.toml\fR in the +current directory, and all parent directories. These configuration files +will be merged with the global configuration file. +.sp +\fB$CARGO_HOME/credentials.toml\fR +.br +\ \ \ \ Private authentication information for logging in to a registry. +.sp +\fB$CARGO_HOME/registry/\fR +.br +\ \ \ \ This directory contains cached downloads of the registry index and any +downloaded dependencies. +.sp +\fB$CARGO_HOME/git/\fR +.br +\ \ \ \ This directory contains cached downloads of git dependencies. +.sp +Please note that the internal structure of the \fB$CARGO_HOME\fR directory is not +stable yet and may be subject to change. +.SH "EXAMPLES" +.sp +.RS 4 +\h'-04' 1.\h'+01'Build a local package and all of its dependencies: +.sp +.RS 4 +.nf +cargo build +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 2.\h'+01'Build a package with optimizations: +.sp +.RS 4 +.nf +cargo build \-\-release +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 3.\h'+01'Run tests for a cross\-compiled target: +.sp +.RS 4 +.nf +cargo test \-\-target i686\-unknown\-linux\-gnu +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 4.\h'+01'Create a new package that builds an executable: +.sp +.RS 4 +.nf +cargo new foobar +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 5.\h'+01'Create a package in the current directory: +.sp +.RS 4 +.nf +mkdir foo && cd foo +cargo init . +.fi +.RE +.RE +.sp +.RS 4 +\h'-04' 6.\h'+01'Learn about a command\[cq]s options and usage: +.sp +.RS 4 +.nf +cargo help clean +.fi +.RE +.RE +.SH "BUGS" +See for issues. +.SH "SEE ALSO" +\fBrustc\fR(1), \fBrustdoc\fR(1) diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/build-std/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/build-std/main.rs new file mode 100644 index 000000000..ffe9f4264 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/build-std/main.rs @@ -0,0 +1,443 @@ +//! A test suite for `-Zbuild-std` which is much more expensive than the +//! standard test suite. +//! +//! This test suite attempts to perform a full integration test where we +//! actually compile the standard library from source (like the real one) and +//! the various tests associated with that. +//! +//! YOU SHOULD IDEALLY NOT WRITE TESTS HERE. +//! +//! If possible, use `tests/testsuite/standard_lib.rs` instead. That uses a +//! 'mock' sysroot which is much faster to compile. The tests here are +//! extremely intensive and are only intended to run on CI and are theoretically +//! not catching any regressions that `tests/testsuite/standard_lib.rs` isn't +//! already catching. +//! +//! All tests here should use `#[cargo_test(build_std_real)]` to indicate that +//! boilerplate should be generated to require the nightly toolchain and the +//! `CARGO_RUN_BUILD_STD_TESTS` env var to be set to actually run these tests. +//! Otherwise the tests are skipped. + +#![allow(clippy::disallowed_methods)] + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, paths, project, rustc_host, str, Execs}; +use std::env; +use std::path::Path; + +fn enable_build_std(e: &mut Execs, arg: Option<&str>, isolated: bool) { + if !isolated { + e.env_remove("CARGO_HOME"); + e.env_remove("HOME"); + } + + // And finally actually enable `build-std` for now + let arg = match arg { + Some(s) => format!("-Zbuild-std={}", s), + None => "-Zbuild-std".to_string(), + }; + e.arg(arg).arg("-Zpublic-dependency"); + e.masquerade_as_nightly_cargo(&["build-std"]); +} + +// Helper methods used in the tests below +trait BuildStd: Sized { + /// Set `-Zbuild-std` args and will download dependencies of the standard + /// library in users's `CARGO_HOME` (`~/.cargo/`) instead of isolated + /// environment `cargo-test-support` usually provides. + /// + /// The environment is not isolated is to avoid excessive network requests + /// and downloads. A side effect is `[BLOCKING]` will show up in stderr, + /// as a sign of package cahce lock contention when running other build-std + /// tests concurrently. + fn build_std(&mut self) -> &mut Self; + + /// Like [`BuildStd::build_std`] and is able to specify what crates to build. + fn build_std_arg(&mut self, arg: &str) -> &mut Self; + + /// Like [`BuildStd::build_std`] but use an isolated `CARGO_HOME` environment + /// to avoid package cache lock contention. + /// + /// Don't use this unless you really need to assert the full stderr + /// and avoid any `[BLOCKING]` message. + fn build_std_isolated(&mut self) -> &mut Self; + fn target_host(&mut self) -> &mut Self; +} + +impl BuildStd for Execs { + fn build_std(&mut self) -> &mut Self { + enable_build_std(self, None, false); + self + } + + fn build_std_arg(&mut self, arg: &str) -> &mut Self { + enable_build_std(self, Some(arg), false); + self + } + + fn build_std_isolated(&mut self) -> &mut Self { + enable_build_std(self, None, true); + self + } + + fn target_host(&mut self) -> &mut Self { + self.arg("--target").arg(rustc_host()); + self + } +} + +#[cargo_test(build_std_real)] +fn basic() { + let p = project() + .file( + "src/main.rs", + " + fn main() { + foo::f(); + } + + #[test] + fn smoke_bin_unit() { + foo::f(); + } + ", + ) + .file( + "src/lib.rs", + " + extern crate alloc; + extern crate proc_macro; + + /// ``` + /// foo::f(); + /// ``` + pub fn f() { + } + + #[test] + fn smoke_lib_unit() { + f(); + } + ", + ) + .file( + "tests/smoke.rs", + " + #[test] + fn smoke_integration() { + foo::f(); + } + ", + ) + .build(); + + // HACK: use an isolated the isolated CARGO_HOME environment (`build_std_isolated`) + // to avoid `[BLOCKING]` messages (from lock contention with other tests) + // from getting in this test's asserts + p.cargo("check").build_std_isolated().target_host().run(); + p.cargo("build") + .build_std_isolated() + .target_host() + // Importantly, this should not say [UPDATING] + // There have been multiple bugs where every build triggers and update. + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("run") + .build_std_isolated() + .target_host() + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/[HOST_TARGET]/debug/foo` + +"#]]) + .run(); + p.cargo("test") + .build_std_isolated() + .target_host() + .with_stderr_data(str![[r#" +[COMPILING] rustc-std-workspace-std [..] +... +[COMPILING] test v0.0.0 ([..]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH]) +[RUNNING] unittests src/main.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH]) +[RUNNING] tests/smoke.rs (target/[HOST_TARGET]/debug/deps/smoke-[HASH]) +[DOCTEST] foo + +"#]]) + .run(); + + // Check for hack that removes dylibs. + let deps_dir = Path::new("target") + .join(rustc_host()) + .join("debug") + .join("deps"); + assert!(p.glob(deps_dir.join("*.rlib")).count() > 0); + assert_eq!(p.glob(deps_dir.join("*.dylib")).count(), 0); +} + +#[cargo_test(build_std_real)] +fn host_proc_macro() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + macro_test = { path = "macro_test" } + "#, + ) + .file( + "src/main.rs", + r#" + extern crate macro_test; + use macro_test::make_answer; + + make_answer!(); + + fn main() { + println!("Hello, World: {}", answer()); + } + "#, + ) + .file( + "macro_test/Cargo.toml", + r#" + [package] + name = "macro_test" + version = "0.1.0" + edition = "2021" + + [lib] + proc-macro = true + "#, + ) + .file( + "macro_test/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro] + pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() + } + "#, + ) + .build(); + + p.cargo("build") + .build_std_arg("std") + .build_std_arg("proc_macro") + .run(); +} + +#[cargo_test(build_std_real)] +fn cross_custom() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [target.custom-target.dependencies] + dep = { path = "dep" } + "#, + ) + .file( + "src/lib.rs", + "#![no_std] pub fn f() -> u32 { dep::answer() }", + ) + .file("dep/Cargo.toml", &basic_manifest("dep", "0.1.0")) + .file("dep/src/lib.rs", "#![no_std] pub fn answer() -> u32 { 42 }") + .file( + "custom-target.json", + r#" + { + "llvm-target": "x86_64-unknown-none-gnu", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + "arch": "x86_64", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "os": "none", + "linker-flavor": "ld.lld" + } + "#, + ) + .build(); + + p.cargo("build --target custom-target.json -v") + .build_std_arg("core") + .run(); +} + +#[cargo_test(build_std_real)] +fn custom_test_framework() { + let p = project() + .file( + "src/lib.rs", + r#" + #![no_std] + #![cfg_attr(test, no_main)] + #![feature(custom_test_frameworks)] + #![test_runner(crate::test_runner)] + + pub fn test_runner(_tests: &[&dyn Fn()]) {} + + #[panic_handler] + fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} + } + "#, + ) + .file( + "target.json", + r#" + { + "llvm-target": "x86_64-unknown-none-gnu", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + "arch": "x86_64", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "os": "none", + "linker-flavor": "ld.lld", + "linker": "rust-lld", + "executables": true, + "panic-strategy": "abort" + } + "#, + ) + .build(); + + // This is a bit of a hack to use the rust-lld that ships with most toolchains. + let sysroot = paths::sysroot(); + let sysroot = Path::new(&sysroot); + let sysroot_bin = sysroot + .join("lib") + .join("rustlib") + .join(rustc_host()) + .join("bin"); + let path = env::var_os("PATH").unwrap_or_default(); + let mut paths = env::split_paths(&path).collect::>(); + paths.insert(0, sysroot_bin); + let new_path = env::join_paths(paths).unwrap(); + + p.cargo("test --target target.json --no-run -v") + .env("PATH", new_path) + .build_std_arg("core") + .run(); +} + +// Fixing rust-lang/rust#117839. +// on macOS it never gets remapped. +// Might be a separate issue, so only run on Linux. +#[cargo_test(build_std_real)] +#[cfg(target_os = "linux")] +fn remap_path_scope() { + let p = project() + .file( + "src/main.rs", + " + fn main() { + panic!(\"remap to /rustc/\"); + } + ", + ) + .file( + ".cargo/config.toml", + " + [profile.release] + debug = \"line-tables-only\" + ", + ) + .build(); + + p.cargo("run --release -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .env("RUST_BACKTRACE", "1") + .build_std() + .target_host() + .with_status(101) + .with_stderr_data( + str![[r#" +[FINISHED] `release` profile [optimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/[HOST_TARGET]/release/foo` +... +[..]thread '[..]' panicked at [..]src/main.rs:3:[..]: +[..]remap to /rustc/[..] +[..]at /rustc/[..]/library/std/src/[..] +[..]at ./src/main.rs:3:[..] +[..]at /rustc/[..]/library/core/src/[..] +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test(build_std_real)] +fn test_proc_macro() { + // See rust-lang/cargo#14735 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2021" + + [lib] + proc-macro = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("test --lib") + .env_remove(cargo_util::paths::dylib_path_envvar()) + .build_std() + .with_stderr_data(str![[r#" +... +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH]) + +"#]]) + .run(); +} + +#[cargo_test(build_std_real)] +fn test_panic_abort() { + // See rust-lang/cargo#14935 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2021" + "#, + ) + .file("src/lib.rs", "#![no_std]") + .build(); + + p.cargo("check") + .build_std_arg("std,panic_abort") + .env("RUSTFLAGS", "-C panic=abort") + .arg("-Zbuild-std-features=panic_immediate_abort") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/advanced_env.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/advanced_env.rs new file mode 100644 index 000000000..d2a117078 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/advanced_env.rs @@ -0,0 +1,37 @@ +//! -Zadvanced-env tests + +use cargo_test_support::prelude::*; +use cargo_test_support::{paths, project, registry::Package}; + +#[cargo_test] +fn source_config_env() { + // Try to define [source] with environment variables. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + somedep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("somedep", "1.0.0") + .local(true) + .file("src/lib.rs", "") + .publish(); + + let path = paths::root().join("registry"); + + p.cargo("check -Zadvanced-env") + .masquerade_as_nightly_cargo(&["advanced-env"]) + .env("CARGO_SOURCE_crates-io_REPLACE_WITH", "my-local-source") + .env("CARGO_SOURCE_my-local-source_LOCAL_REGISTRY", path) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/alt_registry.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/alt_registry.rs new file mode 100644 index 000000000..b281dfc8d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/alt_registry.rs @@ -0,0 +1,1982 @@ +//! Tests for alternative registries. + +use std::fs; + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::prelude::*; +use cargo_test_support::publish::validate_alt_upload; +use cargo_test_support::registry::{self, Package, RegistryBuilder}; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, paths, project}; + +#[cargo_test] +fn depend_on_alt_registry() { + registry::alt_init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").alternative(true).publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[CHECKING] bar v0.0.1 (registry `alternative`) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("clean").run(); + + // Don't download a second time + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.0.1 (registry `alternative`) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn depend_on_alt_registry_depends_on_same_registry_no_index() { + registry::alt_init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").alternative(true).publish(); + Package::new("bar", "0.0.1") + .registry_dep("baz", "0.0.1") + .alternative(true) + .publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.0.1 (registry `alternative`) +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[CHECKING] baz v0.0.1 (registry `alternative`) +[CHECKING] bar v0.0.1 (registry `alternative`) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn depend_on_alt_registry_depends_on_same_registry() { + registry::alt_init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").alternative(true).publish(); + Package::new("bar", "0.0.1") + .registry_dep("baz", "0.0.1") + .alternative(true) + .publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.0.1 (registry `alternative`) +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[CHECKING] baz v0.0.1 (registry `alternative`) +[CHECKING] bar v0.0.1 (registry `alternative`) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn depend_on_alt_registry_depends_on_crates_io() { + registry::alt_init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").publish(); + Package::new("bar", "0.0.1") + .dep("baz", "0.0.1") + .alternative(true) + .publish(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[UPDATING] `alternative` index +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[CHECKING] baz v0.0.1 +[CHECKING] bar v0.0.1 (registry `alternative`) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[CHECKING] foo v0.0.1 ([ROOT]/foo) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn registry_and_path_dep_works() { + registry::alt_init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + path = "bar" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn registry_incompatible_with_git() { + registry::alt_init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + git = "" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dependency (bar) specification is ambiguous. Only one of `git` or `registry` is allowed. + +"#]]) + .run(); +} + +#[cargo_test] +fn cannot_publish_to_crates_io_with_registry_dependency() { + let crates_io = registry::init(); + let _alternative = RegistryBuilder::new().alternative().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").alternative(true).publish(); + + p.cargo("publish") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] crates cannot be published to crates.io with dependencies sourced from other +registries. `bar` needs to be published to crates.io before publishing this crate. +(crate `bar` is pulled from registry `alternative`) + +"#]]) + .run(); + + p.cargo("publish") + .replace_crates_io(crates_io.index_url()) + .arg("--token") + .arg(crates_io.token()) + .arg("--index") + .arg(crates_io.index_url().as_str()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] crates cannot be published to crates.io with dependencies sourced from other +registries. `bar` needs to be published to crates.io before publishing this crate. +(crate `bar` is pulled from registry `alternative`) + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_with_registry_dependency() { + let _reg = RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").alternative(true).publish(); + + p.cargo("publish --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[COMPILING] bar v0.0.1 (registry `alternative`) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `alternative` +[NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` + +"#]]) + .run(); + + validate_alt_upload( + r#"{ + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "bar", + "optional": false, + "target": null, + "version_req": "^0.0.1" + } + ], + "description": null, + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "homepage": null, + "documentation": null, + "rust_version": null, + "vers": "0.0.1" + }"#, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + ); +} + +#[cargo_test] +fn alt_registry_and_crates_io_deps() { + registry::alt_init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies] + crates_io_dep = "0.0.1" + + [dependencies.alt_reg_dep] + version = "0.1.0" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("crates_io_dep", "0.0.1").publish(); + Package::new("alt_reg_dep", "0.1.0") + .alternative(true) + .publish(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[UPDATING] `alternative` index +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] crates_io_dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] alt_reg_dep v0.1.0 (registry `alternative`) +[CHECKING] crates_io_dep v0.0.1 +[CHECKING] alt_reg_dep v0.1.0 (registry `alternative`) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[CHECKING] foo v0.0.1 ([ROOT]/foo) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn block_publish_due_to_no_token() { + registry::alt_init(); + let p = project().file("src/lib.rs", "").build(); + + fs::remove_file(paths::home().join(".cargo/credentials.toml")).unwrap(); + + // Now perform the actual publish + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] no token found for `alternative`, please run `cargo login --registry alternative` +or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_registries_crates_io_protocol() { + let _ = RegistryBuilder::new() + .no_configure_token() + .alternative() + .build(); + // Should not produce a warning due to the registries.crates-io.protocol = 'sparse' configuration + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + "[registries.crates-io] + protocol = 'sparse'", + ) + .build(); + + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] no token found for `alternative`, please run `cargo login --registry alternative` +or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_to_alt_registry() { + let _reg = RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project().file("src/main.rs", "fn main() {}").build(); + + // Now perform the actual publish + p.cargo("publish --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `alternative` +[NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` + +"#]]) + .run(); + + validate_alt_upload( + r#"{ + "authors": [], + "badges": {}, + "categories": [], + "deps": [], + "description": null, + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "homepage": null, + "documentation": null, + "rust_version": null, + "vers": "0.0.1" + }"#, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + ); +} + +#[cargo_test] +fn publish_with_crates_io_dep() { + // crates.io registry. + let _dummy_reg = registry::init(); + // Alternative registry. + let _alt_reg = RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = ["me"] + edition = "2015" + license = "MIT" + description = "foo" + + [dependencies.bar] + version = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("publish --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `dummy-registry` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `alternative` +[NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` + +"#]]) + .run(); + + validate_alt_upload( + r#"{ + "authors": ["me"], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "bar", + "optional": false, + "registry": "https://github.com/rust-lang/crates.io-index", + "target": null, + "version_req": "^0.0.1" + } + ], + "description": "foo", + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "homepage": null, + "documentation": null, + "rust_version": null, + "vers": "0.0.1" + }"#, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + ); +} + +#[cargo_test] +fn passwords_in_registries_index_url_forbidden() { + registry::alt_init(); + + let config = paths::home().join(".cargo/config.toml"); + + fs::write( + config, + r#" + [registries.alternative] + index = "ssh://git:secret@foobar.com" + "#, + ) + .unwrap(); + + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid index URL for registry `alternative` defined in [ROOT]/home/.cargo/config.toml + +Caused by: + registry URLs may not contain passwords + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_alt_reg() { + registry::alt_init(); + Package::new("bar", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { version = "0.1.0", registry = "alternative" } + + [patch.alternative] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + " + extern crate bar; + pub fn f() { bar::bar(); } + ", + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_registry_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "bad name" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character ` ` in registry name: `bad name`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) + + + --> Cargo.toml:8:17 + | + 8 | / [dependencies.bar] + 9 | | version = "0.0.1" +10 | | registry = "bad name" + | |_____________________________________^ + | + +"#]]) + .run(); + + for cmd in &[ + "init", + "install foo", + "login", + "owner", + "publish", + "search", + "yank --version 0.0.1", + ] { + p.cargo(cmd) + .arg("--registry") + .arg("bad name") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character ` ` in registry name: `bad name`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) + +"#]]) + .run(); + } +} + +#[cargo_test] +fn no_api() { + let _registry = RegistryBuilder::new().alternative().no_api().build(); + Package::new("bar", "0.0.1").alternative(true).publish(); + + // First check that a dependency works. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[CHECKING] bar v0.0.1 (registry `alternative`) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("login --registry alternative") + .with_stdin("TOKEN") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] registry `alternative` does not support API commands + +"#]]) + .run(); + + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] registry `alternative` does not support API commands + +"#]]) + .run(); + + p.cargo("search --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] registry `alternative` does not support API commands + +"#]]) + .run(); + + p.cargo("owner --registry alternative --list") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] registry `alternative` does not support API commands + +"#]]) + .run(); + + p.cargo("yank --registry alternative --version=0.0.1 bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] registry `alternative` does not support API commands + +"#]]) + .run(); + + p.cargo("yank --registry alternative --version=0.0.1 bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] registry `alternative` does not support API commands + +"#]]) + .run(); +} + +#[cargo_test] +fn alt_reg_metadata() { + // Check for "registry" entries in `cargo metadata` with alternative registries. + registry::alt_init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + altdep = { version = "0.0.1", registry = "alternative" } + iodep = { version = "0.0.1" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("bar", "0.0.1").publish(); + Package::new("altdep", "0.0.1") + .dep("bar", "0.0.1") + .alternative(true) + .publish(); + Package::new("altdep2", "0.0.1").alternative(true).publish(); + Package::new("iodep", "0.0.1") + .registry_dep("altdep2", "0.0.1") + .publish(); + + // The important thing to check here is the "registry" value in `deps`. + // They should be: + // foo -> altdep: alternative-registry + // foo -> iodep: null (because it is in crates.io) + // altdep -> bar: null (because it is in crates.io) + // iodep -> altdep2: alternative-registry + p.cargo("metadata --format-version=1 --no-deps") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "altdep", + "optional": false, + "registry": "[ROOTURL]/alternative-registry", + "rename": null, + "req": "^0.0.1", + "source": "registry+[ROOTURL]/alternative-registry", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "iodep", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.0.1", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); + + // --no-deps uses a different code path, make sure both work. + p.cargo("metadata --format-version=1") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "bar", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.0.1", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+[ROOTURL]/alternative-registry#altdep@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep-0.0.1/Cargo.toml", + "metadata": null, + "name": "altdep", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+[ROOTURL]/alternative-registry", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "altdep", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep2-0.0.1/Cargo.toml", + "metadata": null, + "name": "altdep2", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+[ROOTURL]/alternative-registry", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "altdep2", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/altdep2-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "altdep", + "optional": false, + "registry": "[ROOTURL]/alternative-registry", + "rename": null, + "req": "^0.0.1", + "source": "registry+[ROOTURL]/alternative-registry", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "iodep", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.0.1", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "altdep2", + "optional": false, + "registry": "[ROOTURL]/alternative-registry", + "rename": null, + "req": "^0.0.1", + "source": "registry+[ROOTURL]/alternative-registry", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/iodep-0.0.1/Cargo.toml", + "metadata": null, + "name": "iodep", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "iodep", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/iodep-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "bar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + } + ], + "features": [], + "id": "registry+[ROOTURL]/alternative-registry#altdep@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + }, + { + "dependencies": [ + "registry+[ROOTURL]/alternative-registry#altdep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "altdep", + "pkg": "registry+[ROOTURL]/alternative-registry#altdep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "iodep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.0.1" + }, + { + "dependencies": [ + "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "altdep2", + "pkg": "registry+[ROOTURL]/alternative-registry#altdep2@0.0.1" + } + ], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.0.1" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn unknown_registry() { + // A known registry refers to an unknown registry. + // foo -> bar(crates.io) -> baz(alt) + registry::alt_init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").alternative(true).publish(); + Package::new("bar", "0.0.1") + .registry_dep("baz", "0.0.1") + .publish(); + + // Remove "alternative" from config. + let cfg_path = paths::home().join(".cargo/config.toml"); + let mut config = fs::read_to_string(&cfg_path).unwrap(); + let start = config.find("[registries.alternative]").unwrap(); + config.insert(start, '#'); + let start_index = &config[start..].find("index =").unwrap(); + config.insert(start + start_index, '#'); + fs::write(&cfg_path, config).unwrap(); + + p.cargo("check").run(); + + // Important parts: + // foo -> bar registry = null + // bar -> baz registry = alternate + p.cargo("metadata --format-version=1") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "baz", + "optional": false, + "registry": "[ROOTURL]/alternative-registry", + "rename": null, + "req": "^0.0.1", + "source": "registry+[ROOTURL]/alternative-registry", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+[ROOTURL]/alternative-registry#baz@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/Cargo.toml", + "metadata": null, + "name": "baz", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+[ROOTURL]/alternative-registry", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "baz", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "bar", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.0.1", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/main.rs", + "test": true + } + ], + "version": "0.0.1" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [ + "registry+[ROOTURL]/alternative-registry#baz@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "baz", + "pkg": "registry+[ROOTURL]/alternative-registry#baz@0.0.1" + } + ], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+[ROOTURL]/alternative-registry#baz@0.0.1" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "bar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.0.1" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn registries_index_relative_url() { + registry::alt_init(); + let config = paths::root().join(".cargo/config.toml"); + fs::create_dir_all(config.parent().unwrap()).unwrap(); + fs::write( + &config, + r#" + [registries.relative] + index = "file:alternative-registry" + "#, + ) + .unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "relative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").alternative(true).publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `relative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `relative`) +[CHECKING] bar v0.0.1 (registry `relative`) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn registries_index_relative_path_not_allowed() { + registry::alt_init(); + let config = paths::root().join(".cargo/config.toml"); + fs::create_dir_all(config.parent().unwrap()).unwrap(); + fs::write( + &config, + r#" + [registries.relative] + index = "alternative-registry" + "#, + ) + .unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + registry = "relative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").alternative(true).publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + invalid index URL for registry `relative` defined in [ROOT]/.cargo/config.toml + +Caused by: + invalid url `alternative-registry`: relative URL without a base + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn both_index_and_registry() { + let p = project().file("src/lib.rs", "").build(); + for cmd in &["publish", "owner", "search", "yank --version 1.0.0"] { + p.cargo(cmd) + .arg("--registry=foo") + .arg("--index=foo") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--registry ' cannot be used with '--index ' + +Usage: [..] + +For more information, try '--help'. + +"#]]) + .run(); + } +} + +#[cargo_test] +fn both_index_and_default() { + let p = project().file("src/lib.rs", "").build(); + for cmd in &[ + "publish", + "owner", + "search", + "yank --version 1.0.0", + "install foo", + ] { + p.cargo(cmd) + .env("CARGO_REGISTRY_DEFAULT", "undefined") + .arg(format!("--index=index_url")) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid url `index_url`: relative URL without a base + +"#]]) + .run(); + } +} + +#[cargo_test] +fn sparse_lockfile() { + let _registry = registry::RegistryBuilder::new() + .http_index() + .alternative() + .build(); + Package::new("foo", "0.1.0").alternative(true).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "a" + version = "0.5.0" + authors = [] + edition = "2015" + + [dependencies] + foo = { registry = 'alternative', version = '0.1.0'} + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + assert_e2e().eq( + &p.read_lockfile(), + str![[r##" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "a" +version = "0.5.0" +dependencies = [ + "foo", +] + +[[package]] +name = "foo" +version = "0.1.0" +source = "sparse+http://127.0.0.1:[..]/index/" +checksum = "458c1addb23fde7dfbca0410afdbcc0086f96197281ec304d9e0e10def3cb899" + +"##]], + ); +} + +#[cargo_test] +fn publish_with_transitive_dep() { + let _alt1 = RegistryBuilder::new() + .http_api() + .http_index() + .alternative_named("Alt-1") + .build(); + let _alt2 = RegistryBuilder::new() + .http_api() + .http_index() + .alternative_named("Alt-2") + .build(); + + let p1 = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + p1.cargo("publish --registry Alt-1").run(); + + let p2 = project() + .file( + "Cargo.toml", + r#" + [package] + name = "b" + version = "0.6.0" + publish = ["Alt-2"] + edition = "2015" + + [dependencies] + a = { version = "0.5.0", registry = "Alt-1" } + "#, + ) + .file("src/lib.rs", "") + .build(); + p2.cargo("publish").run(); +} + +#[cargo_test] +fn warn_for_unused_fields() { + let _ = RegistryBuilder::new() + .no_configure_token() + .alternative() + .build(); + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + "[registry] + unexpected-field = 'foo' + [registries.alternative] + unexpected-field = 'foo' + ", + ) + .build(); + + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[WARNING] unused config key `registries.alternative.unexpected-field` in `[ROOT]/foo/.cargo/config.toml` +[ERROR] no token found for `alternative`, please run `cargo login --registry alternative` +or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +"#]]) + .run(); + + let crates_io = registry::RegistryBuilder::new() + .no_configure_token() + .build(); + p.cargo("publish --registry crates-io") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] unused config key `registry.unexpected-field` in `[ROOT]/foo/.cargo/config.toml` +[ERROR] no token found, please run `cargo login` +or use environment variable CARGO_REGISTRY_TOKEN + +"#]]) + .run(); +} + +#[cargo_test] +fn config_empty_registry_name() { + let _ = RegistryBuilder::new() + .no_configure_token() + .alternative() + .build(); + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + "[registry.''] + ", + ) + .build(); + + p.cargo("publish") + .arg("--registry") + .arg("") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] registry name cannot be empty + +"#]]) + .run(); +} + +#[cargo_test] +fn empty_registry_flag() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("publish") + .arg("--registry") + .arg("") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] registry name cannot be empty + +"#]]) + .run(); +} + +#[cargo_test] +fn empty_dependency_registry() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { version = "0.1.0", registry = "" } + "#, + ) + .file( + "src/lib.rs", + " + extern crate bar; + pub fn f() { bar::bar(); } + ", + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] registry name cannot be empty + + + --> Cargo.toml:8:23 + | +8 | bar = { version = "0.1.0", registry = "" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dep.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dep.rs new file mode 100644 index 000000000..fc4b8f63e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dep.rs @@ -0,0 +1,3409 @@ +//! Tests specific to artifact dependencies, designated using +//! the new `dep = { artifact = "bin", … }` syntax in manifests. + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Package, RegistryBuilder}; +use cargo_test_support::str; +use cargo_test_support::{ + basic_bin_manifest, basic_manifest, cross_compile, project, publish, registry, rustc_host, + Project, +}; + +#[cargo_test] +fn check_with_invalid_artifact_dependency() { + // invalid name + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "unknown" } + "#, + ) + .file("src/lib.rs", "extern crate bar;") // this would fail but we don't get there, artifacts are no libs + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + 'unknown' is not a valid artifact specifier + +"#]]) + .with_status(101) + .run(); + + fn run_cargo_with_and_without_bindeps_feature( + p: &Project, + cmd: &str, + assert: &dyn Fn(&mut cargo_test_support::Execs), + ) { + assert( + p.cargo(&format!("{} -Z bindeps", cmd)) + .masquerade_as_nightly_cargo(&["bindeps"]), + ); + assert(&mut p.cargo(cmd)); + } + + // lib specified without artifact + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar/", lib = true } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + run_cargo_with_and_without_bindeps_feature(&p, "check", &|cargo| { + cargo + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + 'lib' specifier cannot be used without an 'artifact = …' value (bar) + +"#]]) + .with_status(101) + .run(); + }); + + // target specified without artifact + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar/", target = "target" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + run_cargo_with_and_without_bindeps_feature(&p, "check", &|cargo| { + cargo + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + 'target' specifier cannot be used without an 'artifact = …' value (bar) + +"#]]) + .with_status(101) + .run(); + }) +} + +#[cargo_test] +fn check_with_invalid_target_triple() { + // invalid name + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin", target = "unknown-target-triple" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --target unknown-target-triple [..]` ([EXIT_STATUS]: 1) + --- stderr +... + + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn build_without_nightly_aborts_with_error() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin" } + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `artifact = …` requires `-Z bindeps` (bar) + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_artifact_and_no_artifact_dep_to_same_package_within_the_same_dep_category() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin" } + bar_stable = { path = "bar/", package = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[WARNING] foo v0.0.0 ([ROOT]/foo) ignoring invalid dependency `bar_stable` which is missing a lib target +[ERROR] the crate `foo v0.0.0 ([ROOT]/foo)` depends on crate `bar v0.5.0 ([ROOT]/foo/bar)` multiple times with different names + +"#]]) + .run(); +} + +#[cargo_test] +fn features_are_unified_among_lib_and_bin_dep_of_same_target() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies.d1] + path = "d1" + features = ["d1f1"] + artifact = "bin" + lib = true + + [dependencies.d2] + path = "d2" + features = ["d2f2"] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + d1::f1(); + d1::f2(); + d2::f1(); + d2::f2(); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + d1f1 = ["d2"] + + [dependencies.d2] + path = "../d2" + features = ["d2f1"] + optional = true + "#, + ) + .file( + "d1/src/main.rs", + r#"fn main() { + #[cfg(feature = "d1f1")] + d2::f1(); + + // Using f2 is only possible as features are unififed across the same target. + // Our own manifest would only enable f1, and f2 comes in because a parent crate + // enables the feature in its manifest. + #[cfg(feature = "d1f1")] + d2::f2(); + }"#, + ) + .file( + "d1/src/lib.rs", + r#" + #[cfg(feature = "d2")] + extern crate d2; + /// Importing f2 here shouldn't be possible as unless features are unified. + #[cfg(feature = "d1f1")] + pub use d2::{f1, f2}; + "#, + ) + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + d2f1 = [] + d2f2 = [] + "#, + ) + .file( + "d2/src/lib.rs", + r#" + #[cfg(feature = "d2f1")] pub fn f1() {} + #[cfg(feature = "d2f2")] pub fn f2() {} + "#, + ) + .build(); + + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] d2 v0.0.1 ([ROOT]/foo/d2) +[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn features_are_not_unified_among_lib_and_bin_dep_of_different_target() { + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies.d1] + path = "d1" + features = ["d1f1"] + artifact = "bin" + lib = true + target = "$TARGET" + + [dependencies.d2] + path = "d2" + features = ["d2f2"] + "# + .replace("$TARGET", target), + ) + .file( + "src/main.rs", + r#" + fn main() { + // the lib = true part always builds for our current target, unifying dependencies + d1::d2::f1(); + d1::d2::f2(); + d2::f1(); + d2::f2(); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + d1f1 = ["d2"] + + [dependencies.d2] + path = "../d2" + features = ["d2f1"] + optional = true + "#, + ) + .file("d1/src/main.rs", r#"fn main() { + // f1 we set ourselves + d2::f1(); + // As 'main' is only compiled as part of the artifact dependency and since that is not unified + // if the target differs, trying to access f2 is a compile time error as the feature isn't enabled in our dependency tree. + d2::f2(); + }"#) + .file( + "d1/src/lib.rs", + r#" + #[cfg(feature = "d2")] + pub extern crate d2; + "#, + ) + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + d2f1 = [] + d2f2 = [] + "#, + ) + .file( + "d2/src/lib.rs", + r#" + #[cfg(feature = "d2f1")] pub fn f1() {} + #[cfg(feature = "d2f2")] pub fn f2() {} + "#, + ) + .build(); + + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] d2 v0.0.1 ([ROOT]/foo/d2) +[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1) +error[E0425]: cannot find function `f2` in crate `d2` +... + +For more information about this error, try `rustc --explain E0425`. +[ERROR] could not compile `d1` (bin "d1") due to 1 previous error +... + +"#]]) + .run(); +} + +#[cargo_test] +fn feature_resolution_works_for_cfg_target_specification() { + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies.d1] + path = "d1" + artifact = "bin" + target = "$TARGET" + "# + .replace("$TARGET", target), + ) + .file( + "src/main.rs", + r#" + fn main() { + let _b = include_bytes!(env!("CARGO_BIN_FILE_D1")); + } + "#, + ) + .file( + "d1/Cargo.toml", + &r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'$TARGET'.dependencies] + d2 = { path = "../d2" } + "# + .replace("$TARGET", target), + ) + .file( + "d1/src/main.rs", + r#"fn main() { + d1::f(); + }"#, + ) + .file("d1/build.rs", r#"fn main() { }"#) + .file( + "d1/src/lib.rs", + &r#"pub fn f() { + #[cfg(target = "$TARGET")] + d2::f(); + } + "# + .replace("$TARGET", target), + ) + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("d2/build.rs", r#"fn main() { }"#) + .file("d2/src/lib.rs", "pub fn f() {}") + .build(); + + p.cargo("test -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); +} + +#[cargo_test] +fn build_script_with_bin_artifacts() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = ["bin", "staticlib", "cdylib"] } + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", r#" + fn main() { + let baz: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_baz").expect("CARGO_BIN_FILE_BAR_baz").into(); + println!("{}", baz.display()); + assert!(&baz.is_file()); + + let lib: std::path::PathBuf = std::env::var("CARGO_STATICLIB_FILE_BAR_bar").expect("CARGO_STATICLIB_FILE_BAR_bar").into(); + println!("{}", lib.display()); + assert!(&lib.is_file()); + + let lib: std::path::PathBuf = std::env::var("CARGO_CDYLIB_FILE_BAR_bar").expect("CARGO_CDYLIB_FILE_BAR_bar").into(); + println!("{}", lib.display()); + assert!(&lib.is_file()); + + let dir: std::path::PathBuf = std::env::var("CARGO_BIN_DIR_BAR").expect("CARGO_BIN_DIR_BAR").into(); + println!("{}", dir.display()); + assert!(dir.is_dir()); + + let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into(); + println!("{}", bar.display()); + assert!(&bar.is_file()); + + let bar2: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_bar").expect("CARGO_BIN_FILE_BAR_bar").into(); + println!("{}", bar2.display()); + assert_eq!(bar, bar2); + } + "#) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [lib] + crate-type = ["staticlib", "cdylib"] + "#, + ) + // compilation target is native for build scripts unless overridden + .file("bar/src/bin/bar.rs", &format!(r#"fn main() {{ assert_eq!(std::env::var("TARGET").unwrap(), "{}"); }}"#, cross_compile::native())) + .file("bar/src/bin/baz.rs", "fn main() {}") + .file("bar/src/lib.rs", "") + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[COMPILING] foo v0.0.0 ([ROOT]/foo) + +"#]] + .unordered(), + ) + .run(); + + let build_script_output = build_script_output_string(&p, "foo"); + // we need the binary directory for this artifact along with all binary paths + if cfg!(target_env = "msvc") { + assert_e2e().eq( + &build_script_output, + str![[r#" +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/baz[EXE] +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/staticlib/bar-[HASH].lib +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/cdylib/bar.dll +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar[EXE] +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar[EXE] + +"#]], + ); + } else { + assert_e2e().eq( + &build_script_output, + str![[r#" +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/baz-[HASH][EXE] +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/staticlib/libbar-[HASH].a +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/cdylib/[..]bar.[..] +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar-[HASH][EXE] +[ROOT]/foo/target/debug/deps/artifact/bar-[HASH]/bin/bar-[HASH][EXE] + +"#]], + ); + } + + assert!( + !p.bin("bar").is_file(), + "artifacts are located in their own directory, exclusively, and won't be lifted up" + ); + assert!(!p.bin("baz").is_file(),); + assert_artifact_executable_output(&p, "debug", "bar", "bar"); +} + +#[cargo_test] +fn build_script_with_bin_artifact_and_lib_false() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin" } + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + bar::doit() + } + "#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() { bar::doit(); }") + .file( + "bar/src/lib.rs", + r#" + pub fn doit() { + panic!("sentinel"); + } + "#, + ) + .build(); + + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_does_not_contain("[..]sentinel[..]") + .run(); +} + +#[cargo_test] +fn lib_with_bin_artifact_and_lib_false() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin" } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() { + bar::doit() + }"#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() { bar::doit(); }") + .file( + "bar/src/lib.rs", + r#" + pub fn doit() { + panic!("sentinel"); + } + "#, + ) + .build(); + + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_does_not_contain("[..]sentinel[..]") + .run(); +} + +#[cargo_test] +fn build_script_with_selected_dashed_bin_artifact_and_lib_true() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar-baz = { path = "bar/", artifact = "bin:baz-suffix", lib = true } + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", r#" + fn main() { + bar_baz::print_env() + } + "#) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar-baz" + version = "0.5.0" + edition = "2015" + authors = [] + + [[bin]] + name = "bar" + + [[bin]] + name = "baz-suffix" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", r#" + pub fn print_env() { + let dir: std::path::PathBuf = std::env::var("CARGO_BIN_DIR_BAR_BAZ").expect("CARGO_BIN_DIR_BAR_BAZ").into(); + let bin: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_BAZ_baz-suffix").expect("CARGO_BIN_FILE_BAR_BAZ_baz-suffix").into(); + println!("{}", dir.display()); + println!("{}", bin.display()); + assert!(dir.is_dir()); + assert!(&bin.is_file()); + assert!(std::env::var("CARGO_BIN_FILE_BAR_BAZ").is_err(), "CARGO_BIN_FILE_BAR_BAZ isn't set due to name mismatch"); + assert!(std::env::var("CARGO_BIN_FILE_BAR_BAZ_bar").is_err(), "CARGO_BIN_FILE_BAR_BAZ_bar isn't set as binary isn't selected"); + } + "#) + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar-baz v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let build_script_output = build_script_output_string(&p, "foo"); + // we need the binary directory for this artifact and the binary itself + if cfg!(target_env = "msvc") { + assert_e2e().eq( + &build_script_output, + str![[r#" +[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin +[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin/baz_suffix[EXE] + +"#]], + ); + } else { + assert_e2e().eq( + &build_script_output, + str![[r#" +[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin +[ROOT]/foo/target/debug/deps/artifact/bar-baz-[HASH]/bin/baz_suffix-[HASH][EXE] + +"#]], + ); + } + + assert!( + !p.bin("bar").is_file(), + "artifacts are located in their own directory, exclusively, and won't be lifted up" + ); + assert_artifact_executable_output(&p, "debug", "bar", "baz_suffix"); +} + +#[cargo_test] +fn lib_with_selected_dashed_bin_artifact_and_lib_true() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar-baz = { path = "bar/", artifact = ["bin:baz-suffix", "staticlib", "cdylib"], lib = true } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() { + bar_baz::exists(); + + env!("CARGO_BIN_DIR_BAR_BAZ"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_BAZ_baz-suffix")); + let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR_BAZ")); + let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR_BAZ_bar-baz")); + let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR_BAZ_bar_baz")); + let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR_BAZ")); + let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR_BAZ_bar-baz")); + let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR_BAZ_bar_baz")); + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar-baz" + version = "0.5.0" + edition = "2015" + authors = [] + + [lib] + crate-type = ["rlib", "staticlib", "cdylib"] + + [[bin]] + name = "bar" + + [[bin]] + name = "baz-suffix" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn exists() {}") + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar-baz v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!( + !p.bin("bar").is_file(), + "artifacts are located in their own directory, exclusively, and won't be lifted up" + ); + assert_artifact_executable_output(&p, "debug", "bar", "baz_suffix"); +} + +#[cargo_test] +fn allow_artifact_and_no_artifact_dep_to_same_package_within_different_dep_categories() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin" } + + [dev-dependencies] + bar = { path = "bar/", package = "bar" } + "#, + ) + .file( + "src/lib.rs", + r#" + #[cfg(test)] extern crate bar; + pub fn foo() { + env!("CARGO_BIN_DIR_BAR"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + }"#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "") + .build(); + p.cargo("test -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .run(); +} + +#[cargo_test] +fn normal_build_deps_are_picked_up_in_presence_of_an_artifact_build_dep_to_the_same_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar", artifact = "bin:bar" } + + [build-dependencies] + bar = { path = "bar" } + "#, + ) + .file("build.rs", "fn main() { bar::f(); }") + .file( + "src/lib.rs", + r#" + pub fn foo() { + env!("CARGO_BIN_DIR_BAR"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + }"#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn f() {}") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); +} + +#[cargo_test] +fn disallow_using_example_binaries_as_artifacts() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin:one-example" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/examples/one-example.rs", "fn main() {}") + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] dependency `bar` in package `foo` requires a `bin:one-example` artifact to be present. + +"#]]) + .run(); +} + +/// From RFC 3028 +/// +/// > You may also specify separate dependencies with different artifact values, as well as +/// dependencies on the same crate without artifact specified; for instance, you may have a +/// build dependency on the binary of a crate and a normal dependency on the Rust library of the same crate. +#[cargo_test] +fn allow_artifact_and_non_artifact_dependency_to_same_crate() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin" } + + [dependencies] + bar = { path = "bar/" } + "#, + ) + .file("src/lib.rs", r#" + pub fn foo() { + bar::doit(); + assert!(option_env!("CARGO_BIN_FILE_BAR").is_none()); + }"#) + .file( + "build.rs", + r#" + fn main() { + assert!(option_env!("CARGO_BIN_FILE_BAR").is_none(), "no environment variables at build time"); + std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR").expect("BAR present")).status().unwrap(); + }"#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn doit() {}") + .build(); + + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_script_deps_adopt_specified_target_unconditionally() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies.bar] + path = "bar/" + artifact = "bin" + target = "{}" + "#, + target + ), + ) + .file("src/lib.rs", "") + .file("build.rs", r#" + fn main() { + let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into(); + assert!(&bar.is_file()); + }"#) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn doit() {}") + .build(); + + p.cargo("check -v -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains("[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]") + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name foo [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]") + .run(); +} + +/// inverse RFC-3176 +#[cargo_test] +fn build_script_deps_adopt_do_not_allow_multiple_targets_under_different_name_and_same_version() { + if cross_compile::disabled() { + return; + } + + let alternate = cross_compile::alternate(); + let native = cross_compile::native(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies.bar] + path = "bar/" + artifact = "bin" + target = "{}" + + [build-dependencies.bar-native] + package = "bar" + path = "bar/" + artifact = "bin" + target = "{}" + "#, + alternate, + native + ), + ) + .file("src/lib.rs", "") + .file("build.rs", r#" + fn main() { + let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into(); + assert!(&bar.is_file()); + let bar_native: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR_NATIVE_bar").expect("CARGO_BIN_FILE_BAR_NATIVE_bar").into(); + assert!(&bar_native.is_file()); + assert_ne!(bar_native, bar, "should build different binaries due to different targets"); + }"#) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] the crate `foo v0.0.0 ([ROOT]/foo)` depends on crate `bar v0.5.0 ([ROOT]/foo/bar)` multiple times with different names + +"#]]) + .run(); +} + +#[cargo_test] +fn non_build_script_deps_adopt_specified_target_unconditionally() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies.bar] + path = "bar/" + artifact = "bin" + target = "{}" + "#, + target + ), + ) + .file( + "src/lib.rs", + r#"pub fn foo() { let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); }"#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn doit() {}") + .build(); + + p.cargo("check -v -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name foo [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains("[RUNNING] `rustc --crate-name foo [..]") + .run(); +} + +#[cargo_test] +fn no_cross_doctests_works_with_artifacts() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin", lib = true } + "#, + ) + .file( + "src/lib.rs", + r#" + //! ``` + //! env!("CARGO_BIN_DIR_BAR"); + //! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + //! ``` + pub fn foo() { + env!("CARGO_BIN_DIR_BAR"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + } + "#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/lib.rs", r#"pub extern "C" fn c() {}"#) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + let target = rustc_host(); + p.cargo("test -Z bindeps --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .run(); + + println!("c"); + let target = cross_compile::alternate(); + + // This will build the library, but does not build or run doc tests. + // This should probably be a warning or error. + p.cargo("test -Z bindeps -v --doc --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..] +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported +See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information. + +"#]]) + .run(); + + if !cross_compile::can_run_on_host() { + return; + } + + // This tests the library, but does not run the doc tests. + p.cargo("test -Z bindeps -v --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[FRESH] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]--test[..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]` +[NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported +See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information. + +"#]]) + .run(); +} + +#[cargo_test] +fn build_script_deps_adopts_target_platform_if_target_equals_target() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin", target = "target" } + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", r#" + fn main() { + let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into(); + assert!(&bar.is_file()); + }"#) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn doit() {}") + .build(); + + let alternate_target = cross_compile::alternate(); + p.cargo("check -v -Z bindeps --target") + .arg(alternate_target) + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains("[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]") + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..]--target [ALT_TARGET] [..]", + ) + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo [..]--target [ALT_TARGET] [..]", + ) + .run(); +} + +#[cargo_test] +// TODO(ST): rename bar (dependency) to something else and un-ignore this with RFC-3176 +#[cfg_attr(target_env = "msvc", ignore = "msvc not working")] +fn profile_override_basic() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [build-dependencies] + bar = { path = "bar", artifact = "bin" } + + [dependencies] + bar = { path = "bar", artifact = "bin" } + + [profile.dev.build-override] + opt-level = 1 + + [profile.dev] + opt-level = 3 + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build -v -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name build_script_build [..] -C opt-level=1 [..]` +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..] -C opt-level=3 [..]` +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/main.rs [..] -C opt-level=1 [..]` +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..] -C opt-level=1 [..]` +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..] -C opt-level=3 [..]` +[RUNNING] `rustc --crate-name foo [..] -C opt-level=3 [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s +[COMPILING] foo v0.0.1 ([ROOT]/foo) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn dependencies_of_dependencies_work_in_artifacts() { + Package::new("baz", "1.0.0") + .file("src/lib.rs", "pub fn baz() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin" } + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR").expect("BAR present")).status().unwrap(); + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + baz = "1.0.0" + "#, + ) + .file("bar/src/lib.rs", r#"pub fn bar() {baz::baz()}"#) + .file("bar/src/main.rs", r#"fn main() {bar::bar()}"#) + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); + + // cargo tree sees artifacts as the dependency kind they are in and doesn't do anything special with it. + p.cargo("tree -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stdout_data(str![[r#" +foo v0.0.0 ([ROOT]/foo) +[build-dependencies] +└── bar v0.5.0 ([ROOT]/foo/bar) + └── baz v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn artifact_dep_target_specified() { + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + + let p = project() + .file( + "Cargo.toml", + &r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + resolver = "2" + edition = "2015" + + [dependencies] + bindep = { path = "bindep", artifact = "bin", target = "$TARGET" } + "# + .replace("$TARGET", target), + ) + .file("src/lib.rs", "") + .file("bindep/Cargo.toml", &basic_manifest("bindep", "0.0.0")) + .file("bindep/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bindep v0.0.0 ([ROOT]/foo/bindep) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_status(0) + .run(); + + p.cargo("tree -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stdout_data(str![[r#" +foo v0.0.0 ([ROOT]/foo) +└── bindep v0.0.0 ([ROOT]/foo/bindep) + +"#]]) + .with_status(0) + .run(); +} + +/// From issue #10593 +/// The case where: +/// * artifact dep is { target = } +/// * dependency of that artifact dependency specifies the same target +/// * the target is not activated. +#[cargo_test] +fn dep_of_artifact_dep_same_target_specified() { + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [dependencies] + bar = {{ path = "bar", artifact = "bin", target = "{target}" }} + "#, + ), + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + &format!( + r#" + [package] + name = "bar" + version = "0.1.0" + + [target.{target}.dependencies] + baz = {{ path = "../baz" }} + "#, + ), + ) + .file("bar/src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_status(0) + .run(); + + p.cargo("tree -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stdout_data( + r#"... +foo v0.1.0 ([ROOT]/foo) +└── bar v0.1.0 ([ROOT]/foo/bar) + └── baz v0.1.0 ([ROOT]/foo/baz) +"#, + ) + .with_status(0) + .run(); +} + +#[cargo_test] +fn targets_are_picked_up_from_non_workspace_artifact_deps() { + 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("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")); }"#, + ) + .add_dep(dep.artifact("bin", Some(target.to_string()))) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + uses-artifact = { version = "1.0.0" } + "#, + ) + .file( + "src/lib.rs", + r#"pub fn foo() { uses_artifact::uses_artifact(); }"#, + ) + .build(); + + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); +} + +#[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" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── 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_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[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_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "^1.0"` (locked to 1.0.1) + version 1.0.1 requires a Cargo version that supports index version 3 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +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" + edition = "2015" + + [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_data( + r#"... +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[ERROR] failed to download from `[ROOTURL]/dl/pm/1.0.0/download` + +Caused by: + [37] Could[..]t read a file:// file (Couldn't open file [ROOT]/dl/pm/1.0.0/download) +"#, + ) + .with_status(101) + .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")}"#) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin" } + bar_stable = { package = "bar", version = "1.0.0", artifact = "bin" } + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR").expect("BAR present")).status().unwrap(); + std::process::Command::new(std::env::var("CARGO_BIN_FILE_BAR_STABLE_bar").expect("BAR STABLE present")).status().unwrap(); + } + "#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", r#"fn main() {println!("0.5.0")}"#) + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[COMPILING] bar v1.0.0 +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[COMPILING] foo v0.0.0 ([ROOT]/foo) + +"#]] + .unordered(), + ) + .run(); + let build_script_output = build_script_output_string(&p, "foo"); + assert_e2e().eq( + &build_script_output, + str![[r#" +0.5.0 +1.0.0 + +"#]], + ); +} + +#[cargo_test] +fn allow_artifact_and_non_artifact_dependency_to_same_crate_if_these_are_not_the_same_dep_kind() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin", lib = false } + + [dependencies] + bar = { path = "bar/" } + "#, + ) + .file("src/lib.rs", r#" + pub fn foo() { + bar::doit(); + assert!(option_env!("CARGO_BIN_FILE_BAR").is_none()); + }"#) + .file( + "build.rs", + r#"fn main() { + println!("{}", std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR")); + println!("{}", std::env::var("CARGO_BIN_FILE_BAR_bar").expect("CARGO_BIN_FILE_BAR_bar")); + }"#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn doit() {}") + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn prevent_no_lib_warning_with_artifact_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin" } + "#, + ) + .file( + "src/lib.rs", + r#"pub fn foo() { let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); }"#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn show_no_lib_warning_with_artifact_dependencies_that_have_no_lib_but_lib_true() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin" } + + [dependencies] + bar = { path = "bar/", artifact = "bin", lib = true } + "#, + ) + .file("src/lib.rs", "") + .file("src/build.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[WARNING] foo v0.0.0 ([ROOT]/foo) ignoring invalid dependency `bar` which is missing a lib target +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn resolver_2_build_dep_without_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + edition = "2021" + + [build-dependencies] + bar = { path = "bar/", artifact = "bin" } + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", r#" + fn main() { + let bar: std::path::PathBuf = std::env::var("CARGO_BIN_FILE_BAR").expect("CARGO_BIN_FILE_BAR").into(); + assert!(&bar.is_file()); + }"#) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); +} + +#[cargo_test] +fn check_missing_crate_type_in_package_fails() { + for crate_type in &["cdylib", "staticlib", "bin"] { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = {{ path = "bar/", artifact = "{}" }} + "#, + crate_type + ), + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) //no bin, just rlib + .file("bar/src/lib.rs", "") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] dependency `bar` in package `foo` requires a [..] artifact to be present. + +"#]]) + .run(); + } +} + +#[cargo_test] +fn check_target_equals_target_in_non_build_dependency_errors() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin", target = "target" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `target = "target"` in normal- or dev-dependencies has no effect (bar) + +"#]]) + .run(); +} + +#[cargo_test] +fn env_vars_and_build_products_for_various_build_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + resolver = "2" + + [lib] + doctest = true + + [build-dependencies] + bar = { path = "bar/", artifact = ["cdylib", "staticlib"] } + + [dependencies] + bar = { path = "bar/", artifact = "bin", lib = true } + + [dev-dependencies] + bar = { path = "bar/", artifact = "bin:baz" } + "#, + ) + .file("build.rs", r#" + fn main() { + let file: std::path::PathBuf = std::env::var("CARGO_CDYLIB_FILE_BAR").expect("CARGO_CDYLIB_FILE_BAR").into(); + assert!(&file.is_file()); + + let file: std::path::PathBuf = std::env::var("CARGO_STATICLIB_FILE_BAR").expect("CARGO_STATICLIB_FILE_BAR").into(); + assert!(&file.is_file()); + + assert!(std::env::var("CARGO_BIN_FILE_BAR").is_err()); + assert!(std::env::var("CARGO_BIN_FILE_BAR_baz").is_err()); + } + "#) + .file( + "src/lib.rs", + r#" + //! ``` + //! bar::c(); + //! env!("CARGO_BIN_DIR_BAR"); + //! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + //! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar")); + //! let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz")); + //! assert!(option_env!("CARGO_STATICLIB_FILE_BAR").is_none()); + //! assert!(option_env!("CARGO_CDYLIB_FILE_BAR").is_none()); + //! ``` + pub fn foo() { + bar::c(); + env!("CARGO_BIN_DIR_BAR"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar")); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz")); + assert!(option_env!("CARGO_STATICLIB_FILE_BAR").is_none()); + assert!(option_env!("CARGO_CDYLIB_FILE_BAR").is_none()); + } + + #[cfg(test)] + #[test] + fn env_unit() { + env!("CARGO_BIN_DIR_BAR"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar")); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz")); + assert!(option_env!("CARGO_STATICLIB_FILE_BAR").is_none()); + assert!(option_env!("CARGO_CDYLIB_FILE_BAR").is_none()); + } + "#, + ) + .file( + "tests/main.rs", + r#" + #[test] + fn env_integration() { + env!("CARGO_BIN_DIR_BAR"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_bar")); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR_baz")); + }"#, + ) + .file("build.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [lib] + crate-type = ["staticlib", "cdylib", "rlib"] + + [[bin]] + name = "bar" + + [[bin]] + name = "baz" + "#, + ) + .file("bar/src/lib.rs", r#"pub extern "C" fn c() {}"#) + .file("bar/src/main.rs", "fn main() {}") + .build(); + p.cargo("test -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] tests/main.rs (target/debug/deps/main-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_artifact_dep() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + Package::new("bar", "1.0.0").publish(); + Package::new("baz", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + resolver = "2" + + [dependencies] + bar = { version = "1.0", artifact = "bin", lib = true } + + [build-dependencies] + baz = { version = "1.0", artifact = ["bin:a", "cdylib", "staticlib"], target = "target" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish -Z bindeps --no-verify") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +[UPLOADED] foo v0.1.0 to registry `crates-io` +[NOTE] waiting for `foo v0.1.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.1.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "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", + "name": "baz", + "optional": false, + "target": null, + "version_req": "^1.0" + } + ], + "description": "foo", + "documentation": "foo", + "features": {}, + "homepage": "foo", + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": "foo", + "rust_version": null, + "vers": "0.1.0" + } + "#, + "foo-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.1.0" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "foo" +documentation = "foo" +readme = false +license = "MIT" +repository = "foo" +resolver = "2" + +[lib] +name = "foo" +path = "src/lib.rs" + +[dependencies.bar] +version = "1.0" +artifact = ["bin"] +lib = true + +[build-dependencies.baz] +version = "1.0" +artifact = [ + "bin:a", + "cdylib", + "staticlib", +] +target = "target" + +"##]], + )], + ); +} + +#[cargo_test] +fn doc_lib_true() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies.bar] + path = "bar" + artifact = "bin" + lib = true + "#, + ) + .file("src/lib.rs", "extern crate bar; pub fn foo() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("doc -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!(p.root().join("target/doc/bar/index.html").is_file()); + + // Verify that it emits rmeta for the bin and lib dependency. + assert_eq!(p.glob("target/debug/artifact/*.rlib").count(), 0); + assert_eq!(p.glob("target/debug/deps/libbar-*.rmeta").count(), 2); + + p.cargo("doc -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!(p.root().join("target/doc/bar/index.html").is_file()); +} + +#[cargo_test] +fn rustdoc_works_on_libs_with_artifacts_and_lib_false() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + resolver = "2" + + [dependencies.bar] + path = "bar" + artifact = ["bin", "staticlib", "cdylib"] + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() { + env!("CARGO_BIN_DIR_BAR"); + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR")); + let _b = include_bytes!(env!("CARGO_CDYLIB_FILE_BAR_bar")); + let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR")); + let _b = include_bytes!(env!("CARGO_STATICLIB_FILE_BAR_bar")); + }"#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [lib] + crate-type = ["staticlib", "cdylib"] + "#, + ) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("doc -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!( + !p.root().join("target/doc/bar/index.html").is_file(), + "bar is not a lib dependency and thus remains undocumented" + ); +} + +fn assert_artifact_executable_output( + p: &Project, + target_name: &str, + dep_name: &str, + bin_name: &str, +) { + if cfg!(target_env = "msvc") { + assert_eq!( + p.glob(format!( + "target/{}/deps/artifact/{}-*/bin/{}{}", + target_name, + dep_name, + bin_name, + std::env::consts::EXE_SUFFIX + )) + .count(), + 1, + "artifacts are placed into their own output directory to not possibly clash" + ); + } else { + assert_eq!( + p.glob(format!( + "target/{}/deps/artifact/{}-*/bin/{}-*{}", + target_name, + dep_name, + bin_name, + std::env::consts::EXE_SUFFIX + )) + .filter_map(Result::ok) + .filter(|f| f.extension().map_or(true, |ext| ext != "o" && ext != "d")) + .count(), + 1, + "artifacts are placed into their own output directory to not possibly clash" + ); + } +} + +fn build_script_output_string(p: &Project, package_name: &str) -> String { + let paths = p + .glob(format!("target/debug/build/{}-*/output", package_name)) + .collect::, _>>() + .unwrap(); + assert_eq!(paths.len(), 1); + std::fs::read_to_string(&paths[0]).unwrap() +} + +#[cargo_test] +fn build_script_features_for_shared_dependency() { + // When a build script is built and run, its features should match. Here: + // + // foo + // -> artifact on d1 with target + // -> common with features f1 + // + // d1 + // -> common with features f2 + // + // common has features f1 and f2, with a build script. + // + // When common is built as a dependency of d1, it should have features + // `f2` (for the library and the build script). + // + // When common is built as a dependency of foo, it should have features + // `f1` (for the library and the build script). + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + resolver = "2" + + [dependencies] + d1 = { path = "d1", artifact = "bin", target = "$TARGET" } + common = { path = "common", features = ["f1"] } + "# + .replace("$TARGET", target), + ) + .file( + "src/main.rs", + r#" + fn main() { + let _b = include_bytes!(env!("CARGO_BIN_FILE_D1")); + common::f1(); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + + [dependencies] + common = { path = "../common", features = ["f2"] } + "#, + ) + .file( + "d1/src/main.rs", + r#"fn main() { + common::f2(); + }"#, + ) + .file( + "common/Cargo.toml", + r#" + [package] + name = "common" + version = "0.0.1" + edition = "2015" + + [features] + f1 = [] + f2 = [] + "#, + ) + .file( + "common/src/lib.rs", + r#" + #[cfg(feature = "f1")] + pub fn f1() {} + + #[cfg(feature = "f2")] + pub fn f2() {} + "#, + ) + .file( + "common/build.rs", + &r#" + use std::env::var_os; + fn main() { + assert_eq!(var_os("CARGO_FEATURE_F1").is_some(), cfg!(feature="f1")); + assert_eq!(var_os("CARGO_FEATURE_F2").is_some(), cfg!(feature="f2")); + if std::env::var("TARGET").unwrap() == "$TARGET" { + assert!(var_os("CARGO_FEATURE_F1").is_none()); + assert!(var_os("CARGO_FEATURE_F2").is_some()); + } else { + assert!(var_os("CARGO_FEATURE_F1").is_some()); + assert!(var_os("CARGO_FEATURE_F2").is_none()); + } + } + "# + .replace("$TARGET", target), + ) + .build(); + + p.cargo("build -Z bindeps -v") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); +} + +#[cargo_test] +fn calc_bin_artifact_fingerprint() { + // See rust-lang/cargo#10527 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [dependencies] + bar = { path = "bar/", artifact = "bin" } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + let _b = include_bytes!(env!("CARGO_BIN_FILE_BAR")); + } + "#, + ) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/main.rs", r#"fn main() { println!("foo") }"#) + .build(); + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file("bar/src/main.rs", r#"fn main() { println!("bar") }"#); + // Change in artifact bin dep `bar` propagates to `foo`, triggering recompile. + p.cargo("check -v -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[DIRTY] bar v0.5.0 ([ROOT]/foo/bar): the file `bar/src/main.rs` has changed ([..]) +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..]` +[DIRTY] foo v0.1.0 ([ROOT]/foo): the dependency bar was rebuilt +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // All units are fresh. No recompile. + p.cargo("check -v -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[FRESH] bar v0.5.0 ([ROOT]/foo/bar) +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn with_target_and_optional() { + // See rust-lang/cargo#10526 + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + &r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + [dependencies] + d1 = { path = "d1", artifact = "bin", optional = true, target = "$TARGET" } + "# + .replace("$TARGET", target), + ) + .file( + "src/main.rs", + r#" + fn main() { + let _b = include_bytes!(env!("CARGO_BIN_FILE_D1")); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2021" + "#, + ) + .file("d1/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -Z bindeps -F d1 -v") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1) +[RUNNING] `rustc --crate-name d1 [..]--crate-type bin[..] +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]--cfg[..]d1[..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn with_assumed_host_target_and_optional_build_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + [build-dependencies] + d1 = { path = "d1", artifact = "bin", optional = true, target = "target" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + std::env::var("CARGO_BIN_FILE_D1").unwrap(); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2021" + "#, + ) + .file("d1/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -Z bindeps -F d1 -v") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1) +[RUNNING] `rustc --crate-name build_script_build --edition=2021 [..]--crate-type bin[..] +[RUNNING] `rustc --crate-name d1 --edition=2021 [..]--crate-type bin[..] +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo --edition=2021 [..]--cfg[..]d1[..] +[FINISHED] `dev` profile [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn decouple_same_target_transitive_dep_from_artifact_dep() { + // See https://github.com/rust-lang/cargo/issues/11463 + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + a = {{ path = "a" }} + bar = {{ path = "bar", artifact = "bin", target = "{target}" }} + "# + ), + ) + .file( + "src/main.rs", + r#" + fn main() {} + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + a = { path = "../a", features = ["feature"] } + "#, + ) + .file( + "bar/src/main.rs", + r#" + fn main() {} + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2021" + + [dependencies] + b = { path = "../b" } + c = { path = "../c" } + + [features] + feature = ["c/feature"] + "#, + ) + .file( + "a/src/lib.rs", + r#" + use b::Trait as _; + + pub fn use_b_trait(x: &impl c::Trait) { + x.b(); + } + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [dependencies] + c = { path = "../c" } + "#, + ) + .file( + "b/src/lib.rs", + r#" + pub trait Trait { + fn b(&self) {} + } + + impl Trait for T {} + "#, + ) + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.1.0" + edition = "2015" + + [features] + feature = [] + "#, + ) + .file( + "c/src/lib.rs", + r#" + pub trait Trait {} + "#, + ) + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 4 packages to latest compatible versions +[COMPILING] c v0.1.0 ([ROOT]/foo/c) +[COMPILING] b v0.1.0 ([ROOT]/foo/b) +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn decouple_same_target_transitive_dep_from_artifact_dep_lib() { + // See https://github.com/rust-lang/cargo/issues/10837 + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + a = {{ path = "a" }} + b = {{ path = "b", features = ["feature"] }} + bar = {{ path = "bar", artifact = "bin", lib = true, target = "{target}" }} + "# + ), + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2021" + + [dependencies] + a = { path = "../a", features = ["b"] } + b = { path = "../b" } + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "bar/src/main.rs", + r#" + use b::Trait; + + fn main() { + a::A.b() + } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dependencies] + b = { path = "../b", optional = true } + "#, + ) + .file( + "a/src/lib.rs", + r#" + pub struct A; + + #[cfg(feature = "b")] + impl b::Trait for A {} + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [features] + feature = [] + "#, + ) + .file( + "b/src/lib.rs", + r#" + pub trait Trait { + fn b(&self) {} + } + "#, + ) + .build(); + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 3 packages to latest compatible versions +[COMPILING] b v0.1.0 ([ROOT]/foo/b) +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn decouple_same_target_transitive_dep_from_artifact_dep_and_proc_macro() { + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + c = {{ path = "c" }} + bar = {{ path = "bar", artifact = "bin", target = "{target}" }} + "# + ), + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + b = { path = "../b" } + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2021" + + [dependencies] + a = { path = "../a" } + + [lib] + proc-macro = true + "#, + ) + .file("b/src/lib.rs", "") + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.1.0" + edition = "2021" + + [dependencies] + d = { path = "../d", features = ["feature"] } + a = { path = "../a" } + + [lib] + proc-macro = true + "#, + ) + .file( + "c/src/lib.rs", + r#" + use a::Trait; + + fn _c() { + d::D.a() + } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dependencies] + d = { path = "../d" } + "#, + ) + .file( + "a/src/lib.rs", + r#" + pub trait Trait { + fn a(&self) {} + } + + impl Trait for d::D {} + "#, + ) + .file( + "d/Cargo.toml", + r#" + [package] + name = "d" + version = "0.1.0" + edition = "2015" + + [features] + feature = [] + "#, + ) + .file("d/src/lib.rs", "pub struct D;") + .build(); + + p.cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data( + str![[r#" +[LOCKING] 5 packages to latest compatible versions +[COMPILING] d v0.1.0 ([ROOT]/foo/d) +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[COMPILING] b v0.1.0 ([ROOT]/foo/b) +[COMPILING] c v0.1.0 ([ROOT]/foo/c) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] +[COMPILING] foo v0.1.0 ([ROOT]/foo) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn same_target_artifact_dep_sharing() { + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + a = {{ path = "a" }} + bar = {{ path = "bar", artifact = "bin", target = "{target}" }} + "# + ), + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + a = { path = "../a" } + "#, + ) + .file( + "bar/src/main.rs", + r#" + fn main() {} + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo(&format!("build -Z bindeps --target {target}")) + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_transitive_artifact_dependency_with_different_target() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [dependencies] + bar = { path = "bar/" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.0" + edition = "2015" + + [dependencies] + baz = { path = "baz/", artifact = "bin", target = "custom-target" } + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "bar/baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.0.0" + edition = "2015" + + [dependencies] + "#, + ) + .file("bar/baz/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[ERROR] failed to determine target information for target `custom-target`. + Artifact dependency `baz` in package `bar v0.0.0 ([ROOT]/foo/bar)` requires building for `custom-target` + +Caused by: + failed to run `rustc` to learn about target-specific information + +Caused by: + process didn't exit successfully: `rustc [..] ([EXIT_STATUS]: 1) + --- stderr +... + + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn build_only_specified_artifact_library() { + // Create a project with: + // - A crate `bar` with both `staticlib` and `cdylib` as crate-types. + // - A crate `foo` which depends on either the `staticlib` or `cdylib` artifact of bar, + // whose build-script simply checks which library artifacts are present. + let create_project = |artifact_lib| { + project() + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "1.0.0" + + [lib] + crate-type = ["staticlib", "cdylib"] + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "1.0.0" + + [build-dependencies] + bar = {{ path = "bar", artifact = "{artifact_lib}" }} + "#), + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cdylib present: {}", std::env::var_os("CARGO_CDYLIB_FILE_BAR").is_some()); + println!("staticlib present: {}", std::env::var_os("CARGO_STATICLIB_FILE_BAR").is_some()); + } + "#, + ) + .build() + }; + + let cdylib = create_project("cdylib"); + cdylib + .cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); + assert_e2e().eq( + &build_script_output_string(&cdylib, "foo"), + str![[r#" +cdylib present: true +staticlib present: false + +"#]], + ); + + let staticlib = create_project("staticlib"); + staticlib + .cargo("build -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .run(); + assert_e2e().eq( + &build_script_output_string(&staticlib, "foo"), + str![[r#" +cdylib present: false +staticlib present: true + +"#]], + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dir.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dir.rs new file mode 100644 index 000000000..982c68b61 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/artifact_dir.rs @@ -0,0 +1,418 @@ +//! Tests for --artifact-dir flag. + +use std::env; +use std::fs; +use std::path::Path; + +use cargo_test_support::prelude::*; +use cargo_test_support::sleep_ms; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, project}; + +#[cargo_test] +fn binary_with_debug() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .build(); + + p.cargo("build -Z unstable-options --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .enable_mac_dsym() + .run(); + check_dir_contents( + &p.root().join("out"), + &["foo"], + &["foo", "foo.dSYM"], + &["foo.exe", "foo.pdb"], + &["foo.exe"], + ); +} + +#[cargo_test] +fn static_library_with_debug() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [lib] + crate-type = ["staticlib"] + "#, + ) + .file( + "src/lib.rs", + r#" + #[no_mangle] + pub extern "C" fn foo() { println!("Hello, World!") } + "#, + ) + .build(); + + p.cargo("build -Z unstable-options --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .run(); + check_dir_contents( + &p.root().join("out"), + &["libfoo.a"], + &["libfoo.a"], + &["foo.lib"], + &["libfoo.a"], + ); +} + +#[cargo_test] +fn dynamic_library_with_debug() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [lib] + crate-type = ["cdylib"] + "#, + ) + .file( + "src/lib.rs", + r#" + #[no_mangle] + pub extern "C" fn foo() { println!("Hello, World!") } + "#, + ) + .build(); + + p.cargo("build -Z unstable-options --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .enable_mac_dsym() + .run(); + check_dir_contents( + &p.root().join("out"), + &["libfoo.so"], + &["libfoo.dylib", "libfoo.dylib.dSYM"], + &["foo.dll", "foo.dll.exp", "foo.dll.lib", "foo.pdb"], + &["foo.dll", "libfoo.dll.a"], + ); +} + +#[cargo_test] +fn rlib_with_debug() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [lib] + crate-type = ["rlib"] + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() { println!("Hello, World!") } + "#, + ) + .build(); + + p.cargo("build -Z unstable-options --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .run(); + check_dir_contents( + &p.root().join("out"), + &["libfoo.rlib"], + &["libfoo.rlib"], + &["libfoo.rlib"], + &["libfoo.rlib"], + ); +} + +#[cargo_test] +fn include_only_the_binary_from_the_current_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [workspace] + + [dependencies] + utils = { path = "./utils" } + "#, + ) + .file("src/lib.rs", "extern crate utils;") + .file( + "src/main.rs", + r#" + extern crate foo; + extern crate utils; + fn main() { + println!("Hello, World!") + } + "#, + ) + .file("utils/Cargo.toml", &basic_manifest("utils", "0.0.1")) + .file("utils/src/lib.rs", "") + .build(); + + p.cargo("build -Z unstable-options --bin foo --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .enable_mac_dsym() + .run(); + check_dir_contents( + &p.root().join("out"), + &["foo"], + &["foo", "foo.dSYM"], + &["foo.exe", "foo.pdb"], + &["foo.exe"], + ); +} + +#[cargo_test] +fn artifact_dir_is_a_file() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file("out", "") + .build(); + + p.cargo("build -Z unstable-options --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to create directory `[ROOT]/foo/out` + +Caused by: +... + +"#]]) + .run(); +} + +#[cargo_test] +fn replaces_artifacts() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("foo") }"#) + .build(); + + p.cargo("build -Z unstable-options --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .run(); + p.process( + &p.root() + .join(&format!("out/foo{}", env::consts::EXE_SUFFIX)), + ) + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); + + sleep_ms(1000); + p.change_file("src/main.rs", r#"fn main() { println!("bar") }"#); + + p.cargo("build -Z unstable-options --artifact-dir out") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .run(); + p.process( + &p.root() + .join(&format!("out/foo{}", env::consts::EXE_SUFFIX)), + ) + .with_stdout_data(str![[r#" +bar + +"#]]) + .run(); +} + +#[cargo_test] +fn avoid_build_scripts() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/main.rs", "fn main() {}") + .file("a/build.rs", r#"fn main() { println!("hello-build-a"); }"#) + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/main.rs", "fn main() {}") + .file("b/build.rs", r#"fn main() { println!("hello-build-b"); }"#) + .build(); + + p.cargo("build -Z unstable-options --artifact-dir out -vv") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .enable_mac_dsym() + .with_stdout_data( + str![[r#" +[a 0.0.1] hello-build-a +[b 0.0.1] hello-build-b + +"#]] + .unordered(), + ) + .run(); + check_dir_contents( + &p.root().join("out"), + &["a", "b"], + &["a", "a.dSYM", "b", "b.dSYM"], + &["a.exe", "a.pdb", "b.exe", "b.pdb"], + &["a.exe", "b.exe"], + ); +} + +#[cargo_test] +fn cargo_build_artifact_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + artifact-dir = "out" + "#, + ) + .build(); + + p.cargo("build -Z unstable-options") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .enable_mac_dsym() + .run(); + check_dir_contents( + &p.root().join("out"), + &["foo"], + &["foo", "foo.dSYM"], + &["foo.exe", "foo.pdb"], + &["foo.exe"], + ); +} + +#[cargo_test] +fn unsupported_short_artifact_dir_flag() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .build(); + + p.cargo("build -Z unstable-options -O") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '-O' found + + tip: a similar argument exists: '--artifact-dir' + +Usage: cargo[EXE] build [OPTIONS] + +For more information, try '--help'. + +"#]]) + .with_status(1) + .run(); +} + +#[cargo_test] +fn deprecated_out_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .build(); + + p.cargo("build -Z unstable-options --out-dir out") + .masquerade_as_nightly_cargo(&["out-dir"]) + .enable_mac_dsym() + .with_stderr_data(str![[r#" +[WARNING] the --out-dir flag has been changed to --artifact-dir +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + check_dir_contents( + &p.root().join("out"), + &["foo"], + &["foo", "foo.dSYM"], + &["foo.exe", "foo.pdb"], + &["foo.exe"], + ); +} + +#[cargo_test] +fn cargo_build_deprecated_out_dir() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("Hello, World!") }"#) + .file( + ".cargo/config.toml", + r#" + [build] + out-dir = "out" + "#, + ) + .build(); + + p.cargo("build -Z unstable-options") + .masquerade_as_nightly_cargo(&["out-dir"]) + .enable_mac_dsym() + .with_stderr_data(str![[r#" +[WARNING] the out-dir config option has been changed to artifact-dir +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + check_dir_contents( + &p.root().join("out"), + &["foo"], + &["foo", "foo.dSYM"], + &["foo.exe", "foo.pdb"], + &["foo.exe"], + ); +} + +fn check_dir_contents( + artifact_dir: &Path, + expected_linux: &[&str], + expected_mac: &[&str], + expected_win_msvc: &[&str], + expected_win_gnu: &[&str], +) { + let expected = if cfg!(target_os = "windows") { + if cfg!(target_env = "msvc") { + expected_win_msvc + } else { + expected_win_gnu + } + } else if cfg!(target_os = "macos") { + expected_mac + } else { + expected_linux + }; + + let actual = list_dir(artifact_dir); + let mut expected = expected.iter().map(|s| s.to_string()).collect::>(); + expected.sort_unstable(); + assert_eq!(actual, expected); +} + +fn list_dir(dir: &Path) -> Vec { + let mut res = Vec::new(); + for entry in fs::read_dir(dir).unwrap() { + let entry = entry.unwrap(); + res.push(entry.file_name().into_string().unwrap()); + } + res.sort_unstable(); + res +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_config.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_config.rs new file mode 100644 index 000000000..8e7316dd2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_config.rs @@ -0,0 +1,3045 @@ +//! Tests for some invalid .cargo/config files. + +use cargo_test_support::git::cargo_uses_gitoxide; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package}; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, project, rustc_host}; + +#[cargo_test] +fn bad1() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [target] + nonexistent-target = "foo" + "#, + ) + .build(); + p.cargo("check -v --target=nonexistent-target") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] expected table for configuration key `target.nonexistent-target`, but found string in [ROOT]/foo/.cargo/config.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn bad2() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [http] + proxy = 3.0 + "#, + ) + .build(); + p.cargo("publish -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not load Cargo configuration + +Caused by: + failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml` + +Caused by: + failed to parse key `http` + +Caused by: + failed to parse key `proxy` + +Caused by: + found TOML configuration value of unknown type `float` + +"#]]) + .run(); +} + +#[cargo_test] +fn bad3() { + let registry = registry::init(); + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [http] + proxy = true + "#, + ) + .build(); + Package::new("foo", "1.0.0").publish(); + + p.cargo("publish -v") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to update registry `crates-io` + +Caused by: + error in [ROOT]/foo/.cargo/config.toml: `http.proxy` expected a string, but found a boolean + +"#]]) + .run(); +} + +#[cargo_test] +fn bad4() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [cargo-new] + vcs = false + "#, + ) + .build(); + p.cargo("new -v foo") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `foo` package +[ERROR] Failed to create package `foo` at `[ROOT]/foo/foo` + +Caused by: + error in [ROOT]/foo/.cargo/config.toml: `cargo-new.vcs` expected a string, but found a boolean + +"#]]) + .run(); +} + +#[cargo_test] +fn bad6() { + let registry = registry::init(); + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [http] + user-agent = true + "#, + ) + .build(); + Package::new("foo", "1.0.0").publish(); + + p.cargo("publish -v") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to update registry `crates-io` + +Caused by: + error in [ROOT]/foo/.cargo/config.toml: `http.user-agent` expected a string, but found a boolean + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_global_config() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.1.0" + "#, + ) + .file(".cargo/config.toml", "4") + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not load Cargo configuration + +Caused by: + could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml` + +Caused by: + TOML parse error at line 1, column 2 + | + 1 | 4 + | ^ + expected `.`, `=` + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_cargo_lock() { + let p = project() + .file("Cargo.lock", "[[package]]\nfoo = 92") + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock + +Caused by: + TOML parse error at line 1, column 1 + | + 1 | [[package]] + | ^^^^^^^^^^^ + missing field `name` + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicate_packages_in_cargo_lock() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "Cargo.lock", + r#" + [[package]] + name = "foo" + version = "0.0.1" + dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "bar" + version = "0.1.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + + [[package]] + name = "bar" + version = "0.1.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock + +Caused by: + package `bar` is specified twice in the lockfile + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_in_cargo_lock() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "Cargo.lock", + r#" + [[package]] + name = "foo" + version = "0.0.1" + dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "bar" + version = "0.1.0" + source = "You shall not parse" + "#, + ) + .build(); + + p.cargo("check --verbose") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock + +Caused by: + TOML parse error at line 12, column 26 + | + 12 | source = "You shall not parse" + | ^^^^^^^^^^^^^^^^^^^^^ + invalid source `You shall not parse` + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_dependency_in_lockfile() { + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.lock", + r#" + [[package]] + name = "foo" + version = "0.0.1" + dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + "#, + ) + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn bad_git_dependency() { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + foo = {{ git = "{url}" }} + "#, + url = if cargo_uses_gitoxide() { + "git://host.xz" + } else { + "file:.." + } + ), + ) + .file("src/lib.rs", "") + .build(); + + if cargo_uses_gitoxide() { + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `git://host.xz` +[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `foo` + +Caused by: + Unable to update git://host.xz + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/_empty-[HASH] + +Caused by: + URL "git://host.xz" does not specify a path to a repository + +"#]]) + .run(); + } else { + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `file:///` +[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `foo` + +Caused by: + Unable to update file:/// + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/_empty-[HASH] + +Caused by: + 'file:///' is not a valid local file URI; class=Config (7) + +"#]]) + .run(); + }; +} + +#[cargo_test] +fn bad_crate_type() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [lib] + crate-type = ["bad_type", "rlib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about crate-type bad_type information + +Caused by: + process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --crate-type bad_type` ([EXIT_STATUS]: 1) + --- stderr + [ERROR] unknown crate type: `bad_type`[..] + + +"#]]) + .run(); +} + +#[cargo_test] +fn malformed_override() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [target.x86_64-apple-darwin.freetype] + native = { + foo: "bar" + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid inline table +expected `}` + --> Cargo.toml:9:27 + | +9 | native = { + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_toml_missing_package_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + missing field `package.name` + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicate_binary_names() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "qqq" + version = "0.1.0" + edition = "2015" + authors = ["A "] + + [[bin]] + name = "e" + path = "a.rs" + + [[bin]] + name = "e" + path = "b.rs" + "#, + ) + .file("a.rs", r#"fn main() -> () {}"#) + .file("b.rs", r#"fn main() -> () {}"#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + found duplicate binary name e, but all binary targets must have a unique name + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicate_example_names() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "qqq" + version = "0.1.0" + edition = "2015" + authors = ["A "] + + [[example]] + name = "ex" + path = "examples/ex.rs" + + [[example]] + name = "ex" + path = "examples/ex2.rs" + "#, + ) + .file("examples/ex.rs", r#"fn main () -> () {}"#) + .file("examples/ex2.rs", r#"fn main () -> () {}"#) + .build(); + + p.cargo("check --example ex") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + found duplicate example name ex, but all example targets must have a unique name + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicate_bench_names() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "qqq" + version = "0.1.0" + edition = "2015" + authors = ["A "] + + [[bench]] + name = "ex" + path = "benches/ex.rs" + + [[bench]] + name = "ex" + path = "benches/ex2.rs" + "#, + ) + .file("benches/ex.rs", r#"fn main () {}"#) + .file("benches/ex2.rs", r#"fn main () {}"#) + .build(); + + p.cargo("bench") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + found duplicate bench name ex, but all bench targets must have a unique name + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicate_deps() { + let p = project() + .file("shim-bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("shim-bar/src/lib.rs", "pub fn a() {}") + .file("linux-bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("linux-bar/src/lib.rs", "pub fn a() {}") + .file( + "Cargo.toml", + r#" + [package] + name = "qqq" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "shim-bar" } + + [target.x86_64-unknown-linux-gnu.dependencies] + bar = { path = "linux-bar" } + "#, + ) + .file("src/main.rs", r#"fn main () {}"#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + Dependency 'bar' has different source paths depending on the build target. Each dependency must have a single canonical source path irrespective of build target. + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicate_deps_diff_sources() { + let p = project() + .file("shim-bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("shim-bar/src/lib.rs", "pub fn a() {}") + .file("linux-bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("linux-bar/src/lib.rs", "pub fn a() {}") + .file( + "Cargo.toml", + r#" + [package] + name = "qqq" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.i686-unknown-linux-gnu.dependencies] + bar = { path = "shim-bar" } + + [target.x86_64-unknown-linux-gnu.dependencies] + bar = { path = "linux-bar" } + "#, + ) + .file("src/main.rs", r#"fn main () {}"#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + Dependency 'bar' has different source paths depending on the build target. Each dependency must have a single canonical source path irrespective of build target. + +"#]]) + .run(); +} + +#[cargo_test] +fn unused_keys() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [target.foo] + bar = "3" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] unused manifest key: target.foo.bar +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + bulid = "foo" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] unused manifest key: package.bulid +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + build = "foo" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] unused manifest key: lib.build +[CHECKING] foo v0.5.0 ([ROOT]/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unused_keys_in_virtual_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + bulid = "foo" + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + p.cargo("check --workspace") + .with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.bulid +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn empty_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = {} + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dependency (bar) specified without providing a local path, Git repository, version, or workspace dependency to use + +"#]]) + .run(); +} + +#[cargo_test] +fn dev_dependencies2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dev_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition +(in the `foo` package) +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn dev_dependencies2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + + [dev_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `dev_dependencies` is unsupported as of the 2024 edition; instead use `dev-dependencies` + (in the `foo` package) + +"#]]) + .run(); +} + +#[cargo_test] +fn dev_dependencies2_conflict() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dev-dependencies] + a = {path = "a"} + [dev_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `dev_dependencies` is redundant with `dev-dependencies`, preferring `dev-dependencies` in the `foo` package +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn build_dependencies2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [build_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition +(in the `foo` package) +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn build_dependencies2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + + [build_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `build_dependencies` is unsupported as of the 2024 edition; instead use `build-dependencies` + (in the `foo` package) + +"#]]) + .run(); +} + +#[cargo_test] +fn build_dependencies2_conflict() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [build-dependencies] + a = {path = "a"} + [build_dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `build_dependencies` is redundant with `build-dependencies`, preferring `build-dependencies` in the `foo` package +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn lib_crate_type2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + name = "foo" + crate_type = ["staticlib", "dylib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition +(in the `foo` library target) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn lib_crate_type2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [lib] + name = "foo" + crate_type = ["staticlib", "dylib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `crate_type` is unsupported as of the 2024 edition; instead use `crate-type` + (in the `foo` library target) + +"#]]) + .run(); +} + +#[cargo_test] +fn lib_crate_type2_conflict() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + name = "foo" + crate-type = ["rlib", "dylib"] + crate_type = ["staticlib", "dylib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `foo` library target +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn bin_crate_type2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + path = "src/main.rs" + crate_type = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition +(in the `foo` binary target) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn bin_crate_type2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + path = "src/main.rs" + crate_type = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `crate_type` is unsupported as of the 2024 edition; instead use `crate-type` + (in the `foo` binary target) + +"#]]) + .run(); +} + +#[cargo_test] +fn bin_crate_type2_conflict() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + path = "src/main.rs" + crate_type = [] + crate-type = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `foo` binary target +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn examples_crate_type2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [[example]] + name = "ex" + path = "examples/ex.rs" + crate_type = ["proc_macro"] + [[example]] + name = "goodbye" + path = "examples/ex-goodbye.rs" + crate_type = ["rlib", "staticlib"] + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + fn main() { println!("ex"); } + "#, + ) + .file( + "examples/ex-goodbye.rs", + r#" + fn main() { println!("goodbye"); } + "#, + ) + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition +(in the `ex` example target) +[WARNING] `crate_type` is deprecated in favor of `crate-type` and will not work in the 2024 edition +(in the `goodbye` example target) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn examples_crate_type2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [[example]] + name = "ex" + path = "examples/ex.rs" + crate_type = ["proc_macro"] + [[example]] + name = "goodbye" + path = "examples/ex-goodbye.rs" + crate_type = ["rlib", "staticlib"] + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + fn main() { println!("ex"); } + "#, + ) + .file( + "examples/ex-goodbye.rs", + r#" + fn main() { println!("goodbye"); } + "#, + ) + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `crate_type` is unsupported as of the 2024 edition; instead use `crate-type` + (in the `ex` example target) + +"#]]) + .run(); +} + +#[cargo_test] +fn examples_crate_type2_conflict() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [[example]] + name = "ex" + path = "examples/ex.rs" + crate-type = ["rlib", "dylib"] + crate_type = ["proc_macro"] + [[example]] + name = "goodbye" + path = "examples/ex-goodbye.rs" + crate-type = ["rlib", "dylib"] + crate_type = ["rlib", "staticlib"] + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + fn main() { println!("ex"); } + "#, + ) + .file( + "examples/ex-goodbye.rs", + r#" + fn main() { println!("goodbye"); } + "#, + ) + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `ex` example target +[WARNING] `crate_type` is redundant with `crate-type`, preferring `crate-type` in the `goodbye` example target +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn cargo_platform_build_dependencies2() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + + [target.{host}.build_dependencies] + build = {{ path = "build" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "build.rs", + "extern crate build; fn main() { build::build(); }", + ) + .file("build/Cargo.toml", &basic_manifest("build", "0.5.0")) + .file("build/src/lib.rs", "pub fn build() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `build_dependencies` is deprecated in favor of `build-dependencies` and will not work in the 2024 edition +(in the `[HOST_TARGET]` platform target) +[LOCKING] 1 package to latest compatible version +[COMPILING] build v0.5.0 ([ROOT]/foo/build) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + ) + .run(); +} + +#[cargo_test] +fn cargo_platform_build_dependencies2_2024() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + build = "build.rs" + + [target.{host}.build_dependencies] + build = {{ path = "build" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "build.rs", + "extern crate build; fn main() { build::build(); }", + ) + .file("build/Cargo.toml", &basic_manifest("build", "0.5.0")) + .file("build/src/lib.rs", "pub fn build() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `build_dependencies` is unsupported as of the 2024 edition; instead use `build-dependencies` + (in the `[HOST_TARGET]` platform target) + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_platform_build_dependencies2_conflict() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + + [target.{host}.build-dependencies] + build = {{ path = "build" }} + [target.{host}.build_dependencies] + build = {{ path = "build" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "build.rs", + "extern crate build; fn main() { build::build(); }", + ) + .file("build/Cargo.toml", &basic_manifest("build", "0.5.0")) + .file("build/src/lib.rs", "pub fn build() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `build_dependencies` is redundant with `build-dependencies`, preferring `build-dependencies` in the `[HOST_TARGET]` platform target +[LOCKING] 1 package to latest compatible version +[COMPILING] build v0.5.0 ([ROOT]/foo/build) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + + .run(); +} + +#[cargo_test] +fn cargo_platform_dev_dependencies2() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [target.{host}.dev_dependencies] + dev = {{ path = "dev" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "tests/foo.rs", + "extern crate dev; #[test] fn foo() { dev::dev() }", + ) + .file("dev/Cargo.toml", &basic_manifest("dev", "0.5.0")) + .file("dev/src/lib.rs", "pub fn dev() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `dev_dependencies` is deprecated in favor of `dev-dependencies` and will not work in the 2024 edition +(in the `[HOST_TARGET]` platform target) +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_platform_dev_dependencies2_2024() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [target.{host}.dev_dependencies] + dev = {{ path = "dev" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "tests/foo.rs", + "extern crate dev; #[test] fn foo() { dev::dev() }", + ) + .file("dev/Cargo.toml", &basic_manifest("dev", "0.5.0")) + .file("dev/src/lib.rs", "pub fn dev() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `dev_dependencies` is unsupported as of the 2024 edition; instead use `dev-dependencies` + (in the `[HOST_TARGET]` platform target) + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_platform_dev_dependencies2_conflict() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [target.{host}.dev-dependencies] + dev = {{ path = "dev" }} + [target.{host}.dev_dependencies] + dev = {{ path = "dev" }} + "#, + host = host + ), + ) + .file("src/main.rs", "fn main() { }") + .file( + "tests/foo.rs", + "extern crate dev; #[test] fn foo() { dev::dev() }", + ) + .file("dev/Cargo.toml", &basic_manifest("dev", "0.5.0")) + .file("dev/src/lib.rs", "pub fn dev() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `dev_dependencies` is redundant with `dev-dependencies`, preferring `dev-dependencies` in the `[HOST_TARGET]` platform target +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn default_features2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a", features = ["f1"], default_features = false } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["f1"] + f1 = [] + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition +(in the `a` dependency) +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn default_features2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + authors = [] + + [dependencies] + a = { path = "a", features = ["f1"], default_features = false } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["f1"] + f1 = [] + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `default_features` is unsupported as of the 2024 edition; instead use `default-features` + (in the `a` dependency) + +"#]]) + .run(); +} + +#[cargo_test] +fn default_features2_conflict() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a", features = ["f1"], default-features = false, default_features = false } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["f1"] + f1 = [] + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `default_features` is redundant with `default-features`, preferring `default-features` in the `a` dependency +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn workspace_default_features2() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["workspace_only", "dep_workspace_only", "package_only", "dep_package_only"] + + [workspace.dependencies] + dep_workspace_only = { path = "dep_workspace_only", default_features = true } + dep_package_only = { path = "dep_package_only" } + "#, + ) + .file( + "workspace_only/Cargo.toml", + r#" + [package] + name = "workspace_only" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep_workspace_only.workspace = true + "#, + ) + .file("workspace_only/src/lib.rs", "") + .file( + "dep_workspace_only/Cargo.toml", + r#" + [package] + name = "dep_workspace_only" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file("dep_workspace_only/src/lib.rs", "") + .file( + "package_only/Cargo.toml", + r#" + [package] + name = "package_only" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep_package_only = { workspace = true, default_features = true } + "#, + ) + .file("package_only/src/lib.rs", "") + .file( + "dep_package_only/Cargo.toml", + r#" + [package] + name = "dep_package_only" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file("dep_package_only/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +(in the `dep_workspace_only` dependency) +[CHECKING] dep_package_only v0.1.0 ([ROOT]/foo/dep_package_only) +[CHECKING] dep_workspace_only v0.1.0 ([ROOT]/foo/dep_workspace_only) +[CHECKING] package_only v0.1.0 ([ROOT]/foo/package_only) +[CHECKING] workspace_only v0.1.0 ([ROOT]/foo/workspace_only) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[WARNING] [ROOT]/foo/workspace_only/Cargo.toml: `default_features` is deprecated in favor of `default-features` and will not work in the 2024 edition + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn workspace_default_features2_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["workspace_only", "dep_workspace_only", "package_only", "dep_package_only"] + + [workspace.dependencies] + dep_workspace_only = { path = "dep_workspace_only", default_features = true } + dep_package_only = { path = "dep_package_only" } + "#, + ) + .file( + "workspace_only/Cargo.toml", + r#" + [package] + name = "workspace_only" + version = "0.1.0" + edition = "2024" + authors = [] + + [dependencies] + dep_workspace_only.workspace = true + "#, + ) + .file("workspace_only/src/lib.rs", "") + .file( + "dep_workspace_only/Cargo.toml", + r#" + [package] + name = "dep_workspace_only" + version = "0.1.0" + edition = "2024" + authors = [] + "#, + ) + .file("dep_workspace_only/src/lib.rs", "") + .file( + "package_only/Cargo.toml", + r#" + [package] + name = "package_only" + version = "0.1.0" + edition = "2024" + authors = [] + + [dependencies] + dep_package_only = { workspace = true, default_features = true } + "#, + ) + .file("package_only/src/lib.rs", "") + .file( + "dep_package_only/Cargo.toml", + r#" + [package] + name = "dep_package_only" + version = "0.1.0" + edition = "2024" + authors = [] + "#, + ) + .file("dep_package_only/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to load manifest for workspace member `[ROOT]/foo/workspace_only` +referenced by workspace at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse manifest at `[ROOT]/foo/workspace_only/Cargo.toml` + +Caused by: + `default_features` is unsupported as of the 2024 edition; instead use `default-features` + (in the `dep_workspace_only` dependency) + +"#]]) + .run(); +} + +#[cargo_test] +fn lib_proc_macro2() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + proc_macro = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `proc_macro` is deprecated in favor of `proc-macro` and will not work in the 2024 edition +(in the `foo` library target) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn lib_proc_macro2_2024() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2024" + [lib] + proc_macro = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `proc_macro` is unsupported as of the 2024 edition; instead use `proc-macro` + (in the `foo` library target) + +"#]]) + .run(); +} + +#[cargo_test] +fn lib_proc_macro2_conflict() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + proc-macro = false + proc_macro = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check").with_stderr_data(str![[r#" +[WARNING] `proc_macro` is redundant with `proc-macro`, preferring `proc-macro` in the `foo` library target +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn bin_proc_macro2() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + path = "src/main.rs" + proc_macro = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `proc_macro` is deprecated in favor of `proc-macro` and will not work in the 2024 edition +(in the `foo` binary target) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn bin_proc_macro2_2024() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2024" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + path = "src/main.rs" + proc_macro = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `proc_macro` is unsupported as of the 2024 edition; instead use `proc-macro` + (in the `foo` binary target) + +"#]]) + .run(); +} + +#[cargo_test] +fn bin_proc_macro2_conflict() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + path = "src/main.rs" + proc-macro = false + proc_macro = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + foo.cargo("check").with_stderr_data(str![[r#" +[WARNING] `proc_macro` is redundant with `proc-macro`, preferring `proc-macro` in the `foo` binary target +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn invalid_toml_historically_allowed_fails() { + let p = project() + .file(".cargo/config.toml", "[bar] baz = 2") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not load Cargo configuration + +Caused by: + could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml` + +Caused by: + TOML parse error at line 1, column 7 + | + 1 | [bar] baz = 2 + | ^ + invalid table header + expected newline, `#` + +"#]]) + .run(); +} + +#[cargo_test] +fn ambiguous_git_reference() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "http://127.0.0.1" + branch = "master" + tag = "some-tag" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dependency (bar) specification is ambiguous. Only one of `branch`, `tag` or `rev` is allowed. + +"#]]) + .run(); +} + +#[cargo_test] +fn fragment_in_git_url() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "http://127.0.0.1#foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_status(101) + // the following is needed as gitoxide has a different error message + // ... + // [..]127.0.0.1[..] + .with_stderr_data(str![[r#" +[WARNING] URL fragment `#foo` in git URL is ignored for dependency (bar). If you were trying to specify a specific git revision, use `rev = "foo"` in the dependency declaration. +[UPDATING] git repository `http://127.0.0.1/#foo` +... +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update http://127.0.0.1/#foo + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/_empty-[HASH] +... + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config1() { + let p = project() + .file("src/lib.rs", "") + .file(".cargo/config.toml", "[source.foo]") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no source location specified for `source.foo`, need `registry`, `local-registry`, `directory`, or `git` defined + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.crates-io] + registry = 'http://example.com' + replace-with = 'bar' + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update registry `crates-io` + +Caused by: + could not find a configured source with the name `bar` when attempting to lookup `crates-io` (configuration in `[ROOT]/foo/.cargo/config.toml`) + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config3() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.crates-io] + registry = 'https://example.com' + replace-with = 'crates-io' + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update registry `crates-io` + +Caused by: + detected a cycle of `replace-with` sources, the source `crates-io` is eventually replaced with itself (configuration in `[ROOT]/foo/.cargo/config.toml`) + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config4() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.crates-io] + replace-with = 'bar' + + [source.bar] + registry = 'https://example.com' + replace-with = 'crates-io' + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update registry `crates-io` + +Caused by: + detected a cycle of `replace-with` sources, the source `crates-io` is eventually replaced with itself (configuration in `[ROOT]/foo/.cargo/config.toml`) + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config5() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.crates-io] + registry = 'https://example.com' + replace-with = 'bar' + + [source.bar] + registry = 'not a url' + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] configuration key `source.bar.registry` specified an invalid URL (in [ROOT]/foo/.cargo/config.toml) + +Caused by: + invalid url `not a url`: relative URL without a base + +"#]]) + .run(); +} + +#[cargo_test] +fn both_git_and_path_specified() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "http://127.0.0.1" + path = "bar" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dependency (bar) specification is ambiguous. Only one of `git` or `path` is allowed. + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config6() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.crates-io] + registry = 'https://example.com' + replace-with = ['not', 'a', 'string'] + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `source.crates-io.replace-with` + +Caused by: + error in [ROOT]/foo/.cargo/config.toml: `source.crates-io.replace-with` expected a string, but found a array + +"#]]) + .run(); +} + +#[cargo_test] +fn ignored_git_revision() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + branch = "spam" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + key `branch` is ignored for dependency (bar). + +"#]]) + .run(); + + // #11540, check that [target] dependencies fail the same way. + foo.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [target.some-target.dependencies] + bar = { path = "bar", branch = "spam" } + "#, + ); + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + key `branch` is ignored for dependency (bar). + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config7() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.foo] + registry = 'https://example.com' + local-registry = 'file:///another/file' + "#, + ) + .build(); + + Package::new("bar", "0.1.0").publish(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] more than one source location specified for `source.foo` + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_source_config8() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.foo] + branch = "somebranch" + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] source definition `source.foo` specifies `branch`, but that requires a `git` key to be specified (in [ROOT]/foo/.cargo/config.toml) + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_dependency() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + bar = 3 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: integer `3`, expected a version string like "0.9.8" or a detailed dependency like { version = "0.9.8" } + --> Cargo.toml:9:23 + | +9 | bar = 3 + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_debuginfo() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.dev] + debug = 'a' + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid value: string "a", expected a boolean, 0, 1, 2, "none", "limited", "full", "line-tables-only", or "line-directives-only" + --> Cargo.toml:9:25 + | +9 | debug = 'a' + | ^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_debuginfo2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.dev] + debug = 3.6 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: floating point `3.6`, expected a boolean, 0, 1, 2, "none", "limited", "full", "line-tables-only", or "line-directives-only" + --> Cargo.toml:9:25 + | +9 | debug = 3.6 + | ^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_opt_level() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = 3 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: integer `3`, expected a boolean or string + --> Cargo.toml:7:25 + | +7 | build = 3 + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_semver_metadata() { + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [dependencies] + bar = "1.0.0+1234" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] version requirement `1.0.0+1234` for dependency `bar` includes semver metadata which will be ignored, removing the metadata is recommended to avoid confusion +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] bar v1.0.0 +[CHECKING] foo v1.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[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_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/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_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `http.ssl-version` + +Caused by: + error in [ROOT]/foo/.cargo/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_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/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_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `build.target` + +Caused by: + error in [ROOT]/foo/.cargo/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. + // + // The error message is a bit unfortunate here. The type here ends up + // being essentially Value>, and each layer of "Value" + // adds some context to the error message. Also, untagged enums provide + // strange error messages. Hopefully most users will be able to untangle + // the message. + let p = project() + .file( + ".cargo/config.toml", + r#" + [target.'cfg(not(target_os = "none"))'] + runner = false + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `target.'cfg(not(target_os = "none"))'.runner` + +Caused by: + error in [ROOT]/foo/.cargo/config.toml: could not load config key `target.'cfg(not(target_os = "none"))'.runner` + +Caused by: + invalid configuration for key `target.'cfg(not(target_os = "none"))'.runner` + expected a string or array of strings, but found a boolean for `target.'cfg(not(target_os = "none"))'.runner` in [ROOT]/foo/.cargo/config.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_target_links_overrides() { + // Invalid parsing of links overrides. + // + // This error message is terrible. Nothing in the deserialization path is + // using config::Value<>, so nothing is able to report the location. I + // think this illustrates how the way things break down with how it + // currently is designed with serde. + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.somelib] + rustc-flags = 'foo' + "#, + rustc_host() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r" +[ERROR] Only `-l` and `-L` flags are allowed in target config `target.[..].rustc-flags` (in [..]foo/.cargo/config.toml): `foo` + +"]]) + .run(); + + p.change_file( + ".cargo/config.toml", + &format!( + "[target.{}.somelib] + warning = \"foo\" + ", + rustc_host(), + ), + ); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `warning` is not supported in build script overrides + +"#]]) + .run(); +} + +#[cargo_test] +fn redefined_sources() { + // Cannot define a source multiple times. + let p = project() + .file( + ".cargo/config.toml", + r#" + [source.foo] + registry = "https://github.com/rust-lang/crates.io-index" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] source `foo` defines source registry `crates-io`, but that source is already defined by `crates-io` +[NOTE] Sources are not allowed to be defined multiple times. + +"#]]) + .run(); + + p.change_file( + ".cargo/config.toml", + r#" + [source.one] + directory = "index" + + [source.two] + directory = "index" + "#, + ); + + // Name is `[..]` because we can't guarantee the order. + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] source `[..]` defines source dir [ROOT]/foo/index, but that source is already defined by `[..]` +[NOTE] Sources are not allowed to be defined multiple times. + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_trim_paths() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [profile.dev] + trim-paths = "split-debuginfo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Ztrim-paths") + .masquerade_as_nightly_cargo(&["trim-paths"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] expected a boolean, "none", "diagnostics", "macro", "object", "all", or an array with these options + --> Cargo.toml:8:30 + | +8 | trim-paths = "split-debuginfo" + | ^^^^^^^^^^^^^^^^^ + | + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_manifest_path.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_manifest_path.rs new file mode 100644 index 000000000..d4cc16fbb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bad_manifest_path.rs @@ -0,0 +1,412 @@ +//! Tests for invalid --manifest-path arguments. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_bin_manifest, main_file, project, str}; + +#[track_caller] +fn assert_not_a_cargo_toml(command: &str, manifest_path_argument: &str) { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo(command) + .arg("--manifest-path") + .arg(manifest_path_argument) + .cwd(p.root().parent().unwrap()) + .with_status(101) + .with_stderr_data("[ERROR] the manifest-path must be a path to a Cargo.toml file\n") + .run(); +} + +#[track_caller] +fn assert_cargo_toml_doesnt_exist(command: &str, manifest_path_argument: &str) { + let p = project().build(); + let expected_path = manifest_path_argument + .split('/') + .collect::>() + .join("[..]"); + + p.cargo(command) + .arg("--manifest-path") + .arg(manifest_path_argument) + .cwd(p.root().parent().unwrap()) + .with_status(101) + .with_stderr_data(format!( + "[ERROR] manifest path `{}` does not exist\n", + expected_path + )) + .run(); +} + +#[cargo_test] +fn bench_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("bench", "foo"); +} + +#[cargo_test] +fn bench_dir_plus_file() { + assert_not_a_cargo_toml("bench", "foo/bar"); +} + +#[cargo_test] +fn bench_dir_plus_path() { + assert_not_a_cargo_toml("bench", "foo/bar/baz"); +} + +#[cargo_test] +fn bench_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("bench", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn build_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("check", "foo"); +} + +#[cargo_test] +fn build_dir_plus_file() { + assert_not_a_cargo_toml("bench", "foo/bar"); +} + +#[cargo_test] +fn build_dir_plus_path() { + assert_not_a_cargo_toml("bench", "foo/bar/baz"); +} + +#[cargo_test] +fn build_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("check", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn clean_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("clean", "foo"); +} + +#[cargo_test] +fn clean_dir_plus_file() { + assert_not_a_cargo_toml("clean", "foo/bar"); +} + +#[cargo_test] +fn clean_dir_plus_path() { + assert_not_a_cargo_toml("clean", "foo/bar/baz"); +} + +#[cargo_test] +fn clean_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("clean", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn doc_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("doc", "foo"); +} + +#[cargo_test] +fn doc_dir_plus_file() { + assert_not_a_cargo_toml("doc", "foo/bar"); +} + +#[cargo_test] +fn doc_dir_plus_path() { + assert_not_a_cargo_toml("doc", "foo/bar/baz"); +} + +#[cargo_test] +fn doc_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("doc", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn fetch_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("fetch", "foo"); +} + +#[cargo_test] +fn fetch_dir_plus_file() { + assert_not_a_cargo_toml("fetch", "foo/bar"); +} + +#[cargo_test] +fn fetch_dir_plus_path() { + assert_not_a_cargo_toml("fetch", "foo/bar/baz"); +} + +#[cargo_test] +fn fetch_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("fetch", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn generate_lockfile_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("generate-lockfile", "foo"); +} + +#[cargo_test] +fn generate_lockfile_dir_plus_file() { + assert_not_a_cargo_toml("generate-lockfile", "foo/bar"); +} + +#[cargo_test] +fn generate_lockfile_dir_plus_path() { + assert_not_a_cargo_toml("generate-lockfile", "foo/bar/baz"); +} + +#[cargo_test] +fn generate_lockfile_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("generate-lockfile", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn package_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("package", "foo"); +} + +#[cargo_test] +fn package_dir_plus_file() { + assert_not_a_cargo_toml("package", "foo/bar"); +} + +#[cargo_test] +fn package_dir_plus_path() { + assert_not_a_cargo_toml("package", "foo/bar/baz"); +} + +#[cargo_test] +fn package_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("package", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn pkgid_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("pkgid", "foo"); +} + +#[cargo_test] +fn pkgid_dir_plus_file() { + assert_not_a_cargo_toml("pkgid", "foo/bar"); +} + +#[cargo_test] +fn pkgid_dir_plus_path() { + assert_not_a_cargo_toml("pkgid", "foo/bar/baz"); +} + +#[cargo_test] +fn pkgid_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("pkgid", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn publish_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("publish", "foo"); +} + +#[cargo_test] +fn publish_dir_plus_file() { + assert_not_a_cargo_toml("publish", "foo/bar"); +} + +#[cargo_test] +fn publish_dir_plus_path() { + assert_not_a_cargo_toml("publish", "foo/bar/baz"); +} + +#[cargo_test] +fn publish_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("publish", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn read_manifest_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("read-manifest", "foo"); +} + +#[cargo_test] +fn read_manifest_dir_plus_file() { + assert_not_a_cargo_toml("read-manifest", "foo/bar"); +} + +#[cargo_test] +fn read_manifest_dir_plus_path() { + assert_not_a_cargo_toml("read-manifest", "foo/bar/baz"); +} + +#[cargo_test] +fn read_manifest_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("read-manifest", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn run_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("run", "foo"); +} + +#[cargo_test] +fn run_dir_plus_file() { + assert_not_a_cargo_toml("run", "foo/bar"); +} + +#[cargo_test] +fn run_dir_plus_path() { + assert_not_a_cargo_toml("run", "foo/bar/baz"); +} + +#[cargo_test] +fn run_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("run", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn rustc_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("rustc", "foo"); +} + +#[cargo_test] +fn rustc_dir_plus_file() { + assert_not_a_cargo_toml("rustc", "foo/bar"); +} + +#[cargo_test] +fn rustc_dir_plus_path() { + assert_not_a_cargo_toml("rustc", "foo/bar/baz"); +} + +#[cargo_test] +fn rustc_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("rustc", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn test_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("test", "foo"); +} + +#[cargo_test] +fn test_dir_plus_file() { + assert_not_a_cargo_toml("test", "foo/bar"); +} + +#[cargo_test] +fn test_dir_plus_path() { + assert_not_a_cargo_toml("test", "foo/bar/baz"); +} + +#[cargo_test] +fn test_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("test", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn update_dir_containing_cargo_toml() { + assert_not_a_cargo_toml("update", "foo"); +} + +#[cargo_test] +fn update_dir_plus_file() { + assert_not_a_cargo_toml("update", "foo/bar"); +} + +#[cargo_test] +fn update_dir_plus_path() { + assert_not_a_cargo_toml("update", "foo/bar/baz"); +} + +#[cargo_test] +fn update_dir_to_nonexistent_cargo_toml() { + assert_cargo_toml_doesnt_exist("update", "foo/bar/baz/Cargo.toml"); +} + +#[cargo_test] +fn verify_project_dir_containing_cargo_toml() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("verify-project --manifest-path foo") + .cwd(p.root().parent().unwrap()) + .with_status(1) + .with_stdout_data( + str![[r#" +[ + { + "invalid": "the manifest-path must be a path to a Cargo.toml file" + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn verify_project_dir_plus_file() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("verify-project --manifest-path foo/bar") + .cwd(p.root().parent().unwrap()) + .with_status(1) + .with_stdout_data( + str![[r#" +[ + { + "invalid": "the manifest-path must be a path to a Cargo.toml file" + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn verify_project_dir_plus_path() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("verify-project --manifest-path foo/bar/baz") + .cwd(p.root().parent().unwrap()) + .with_status(1) + .with_stdout_data( + str![[r#" +[ + { + "invalid": "the manifest-path must be a path to a Cargo.toml file" + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn verify_project_dir_to_nonexistent_cargo_toml() { + let p = project().build(); + p.cargo("verify-project --manifest-path foo/bar/baz/Cargo.toml") + .cwd(p.root().parent().unwrap()) + .with_status(1) + .with_stdout_data( + str![[r#" +[ + { + "invalid": "manifest path `foo/bar/baz/Cargo.toml` does not exist" + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bench.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bench.rs new file mode 100644 index 000000000..258af709f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/bench.rs @@ -0,0 +1,2129 @@ +//! Tests for the `cargo bench` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project, str}; + +#[cargo_test(nightly, reason = "bench")] +fn cargo_bench_simple() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[bench] + fn bench_hello(_b: &mut test::Bencher) { + assert_eq!(hello(), "hello") + } + "#, + ) + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench_hello ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_bench_implicit() { + let p = project() + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + fn main() { println!("Hello main!"); } + "#, + ) + .file( + "tests/other.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run3(_ben: &mut test::Bencher) { } + "#, + ) + .file( + "benches/mybench.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run2(_ben: &mut test::Bencher) { } + "#, + ) + .build(); + + p.cargo("bench --benches") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) +[RUNNING] [..] (target/release/deps/mybench-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test run1 ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test run2 ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_bin_implicit() { + let p = project() + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + fn main() { println!("Hello main!"); } + "#, + ) + .file( + "tests/other.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run3(_ben: &mut test::Bencher) { } + "#, + ) + .file( + "benches/mybench.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run2(_ben: &mut test::Bencher) { } + "#, + ) + .build(); + + p.cargo("bench --bins") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test run1 ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_tarname() { + let p = project() + .file( + "benches/bin1.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + "#, + ) + .file( + "benches/bin2.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run2(_ben: &mut test::Bencher) { } + "#, + ) + .build(); + + p.cargo("bench --bench bin2") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/bin2-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test run2 ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_multiple_targets() { + let p = project() + .file( + "benches/bin1.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + "#, + ) + .file( + "benches/bin2.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run2(_ben: &mut test::Bencher) { } + "#, + ) + .file( + "benches/bin3.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run3(_ben: &mut test::Bencher) { } + "#, + ) + .build(); + + // This should not have anything about `run3` in it. + p.cargo("bench --bench bin1 --bench bin2") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/bin1.rs (target/release/deps/bin1-[HASH][EXE]) +[RUNNING] benches/bin2.rs (target/release/deps/bin2-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn cargo_bench_verbose() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + fn main() {} + #[bench] fn bench_hello(_b: &mut test::Bencher) {} + "#, + ) + .build(); + + p.cargo("bench -v hello") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/main.rs [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[..]target/release/deps/foo-[HASH][EXE] hello --bench` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench_hello ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn many_similar_names() { + let p = project() + .file( + "src/lib.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate test; + pub fn foo() {} + #[bench] fn lib_bench(_b: &mut test::Bencher) {} + ", + ) + .file( + "src/main.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate foo; + #[cfg(test)] + extern crate test; + fn main() {} + #[bench] fn bin_bench(_b: &mut test::Bencher) { foo::foo() } + ", + ) + .file( + "benches/foo.rs", + r#" + #![feature(test)] + extern crate foo; + extern crate test; + #[bench] fn bench_bench(_b: &mut test::Bencher) { foo::foo() } + "#, + ) + .build(); + + p.cargo("bench") + .with_stdout_data(str![[r#" + +running 1 test +test lib_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bin_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn cargo_bench_failing_test() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[bench] + fn bench_hello(_b: &mut test::Bencher) { + assert_eq!(hello(), "nope", "NOPE!") + } + "#, + ) + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); + + // Force libtest into serial execution so that the test header will be printed. + p.cargo("bench -- --test-threads=1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) +[ERROR] bench failed, to rerun pass `--bin foo` + +"#]]) + .with_stdout_data("...\n[..]NOPE![..]\n...") + .with_status(101) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_with_lib_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "baz" + path = "src/main.rs" + "#, + ) + .file( + "src/lib.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + /// + /// ```rust + /// extern crate foo; + /// fn main() { + /// println!("{}", foo::foo()); + /// } + /// ``` + /// + pub fn foo(){} + #[bench] fn lib_bench(_b: &mut test::Bencher) {} + "#, + ) + .file( + "src/main.rs", + " + #![feature(test)] + #[allow(unused_extern_crates)] + extern crate foo; + #[cfg(test)] + extern crate test; + + fn main() {} + + #[bench] + fn bin_bench(_b: &mut test::Bencher) {} + ", + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) +[RUNNING] [..] (target/release/deps/baz-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test lib_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bin_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_with_deep_lib_dep() { + let p = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.foo] + path = "../foo" + "#, + ) + .file( + "src/lib.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate foo; + #[cfg(test)] + extern crate test; + #[bench] + fn bar_bench(_b: &mut test::Bencher) { + foo::foo(); + } + ", + ) + .build(); + let _p2 = project() + .file( + "src/lib.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate test; + + pub fn foo() {} + + #[bench] + fn foo_bench(_b: &mut test::Bencher) {} + ", + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] bar v0.0.1 ([ROOT]/bar) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/bar-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bar_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn external_bench_explicit() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bench]] + name = "bench" + path = "src/bench.rs" + "#, + ) + .file( + "src/lib.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + pub fn get_hello() -> &'static str { "Hello" } + + #[bench] + fn internal_bench(_b: &mut test::Bencher) {} + "#, + ) + .file( + "src/bench.rs", + r#" + #![feature(test)] + #[allow(unused_extern_crates)] + extern crate foo; + extern crate test; + + #[bench] + fn external_bench(_b: &mut test::Bencher) {} + "#, + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) +[RUNNING] [..] (target/release/deps/bench-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test internal_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test external_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn external_bench_implicit() { + let p = project() + .file( + "src/lib.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + pub fn get_hello() -> &'static str { "Hello" } + + #[bench] + fn internal_bench(_b: &mut test::Bencher) {} + "#, + ) + .file( + "benches/external.rs", + r#" + #![feature(test)] + #[allow(unused_extern_crates)] + extern crate foo; + extern crate test; + + #[bench] + fn external_bench(_b: &mut test::Bencher) {} + "#, + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) +[RUNNING] [..] (target/release/deps/external-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test internal_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test external_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_autodiscover_2015() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2015" + + [features] + magic = [] + + [[bench]] + name = "bench_magic" + required-features = ["magic"] + "#, + ) + .file("src/lib.rs", "") + .file( + "benches/bench_basic.rs", + r#" + #![feature(test)] + #[allow(unused_extern_crates)] + extern crate foo; + extern crate test; + + #[bench] + fn bench_basic(_b: &mut test::Bencher) {} + "#, + ) + .file( + "benches/bench_magic.rs", + r#" + #![feature(test)] + #[allow(unused_extern_crates)] + extern crate foo; + extern crate test; + + #[bench] + fn bench_magic(_b: &mut test::Bencher) {} + "#, + ) + .build(); + + p.cargo("bench bench_basic") + .with_stderr_data(str![[r#" +[WARNING] An explicit [[bench]] section is specified in Cargo.toml which currently +disables Cargo from automatically inferring other benchmark targets. +This inference behavior will change in the Rust 2018 edition and the following +files will be included as a benchmark target: + +* [..]bench_basic.rs + +This is likely to break cargo build or cargo test as these files may not be +ready to be compiled as a benchmark target today. You can future-proof yourself +and disable this warning by adding `autobenches = false` to your [package] +section. You may also move the files to a location where Cargo would not +automatically infer them to be a target, such as in subfolders. + +For more information on this warning you can consult +https://github.com/rust-lang/cargo/issues/5330 +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn dont_run_examples() { + let p = project() + .file("src/lib.rs", "") + .file( + "examples/dont-run-me-i-will-fail.rs", + r#"fn main() { panic!("Examples should not be run by 'cargo test'"); }"#, + ) + .build(); + p.cargo("bench").run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn pass_through_command_line() { + let p = project() + .file( + "src/lib.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate test; + + #[bench] fn foo(_b: &mut test::Bencher) {} + #[bench] fn bar(_b: &mut test::Bencher) {} + ", + ) + .build(); + + p.cargo("bench bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bar ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 1 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("bench foo") + .with_stderr_data(str![[r#" +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 1 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +// Regression test for running cargo-bench twice with +// tests in an rlib +#[cargo_test(nightly, reason = "bench")] +fn cargo_bench_twice() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/foo.rs", + r#" + #![crate_type = "rlib"] + #![feature(test)] + #[cfg(test)] + extern crate test; + + #[bench] + fn dummy_bench(b: &mut test::Bencher) { } + "#, + ) + .build(); + + for _ in 0..2 { + p.cargo("bench").run(); + } +} + +#[cargo_test(nightly, reason = "bench")] +fn lib_bin_same_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + [[bin]] + name = "foo" + "#, + ) + .file( + "src/lib.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate test; + #[bench] fn lib_bench(_b: &mut test::Bencher) {} + ", + ) + .file( + "src/main.rs", + " + #![feature(test)] + #[allow(unused_extern_crates)] + extern crate foo; + #[cfg(test)] + extern crate test; + + #[bench] + fn bin_bench(_b: &mut test::Bencher) {} + ", + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test lib_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bin_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn lib_with_standard_name() { + let p = project() + .file("Cargo.toml", &basic_manifest("syntax", "0.0.1")) + .file( + "src/lib.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate test; + + /// ``` + /// syntax::foo(); + /// ``` + pub fn foo() {} + + #[bench] + fn foo_bench(_b: &mut test::Bencher) {} + ", + ) + .file( + "benches/bench.rs", + " + #![feature(test)] + extern crate syntax; + extern crate test; + + #[bench] + fn bench(_b: &mut test::Bencher) { syntax::foo() } + ", + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] syntax v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/syntax-[HASH][EXE]) +[RUNNING] [..] (target/release/deps/bench-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo_bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn lib_with_standard_name2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "syntax" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "syntax" + bench = false + doctest = false + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate syntax; + #[cfg(test)] + extern crate test; + + fn main() {} + + #[bench] + fn bench(_b: &mut test::Bencher) { syntax::foo() } + ", + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] syntax v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/syntax-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_dylib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + crate-type = ["dylib"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + "src/lib.rs", + r#" + #![feature(test)] + extern crate bar as the_bar; + #[cfg(test)] + extern crate test; + + pub fn bar() { the_bar::baz(); } + + #[bench] + fn foo(_b: &mut test::Bencher) {} + "#, + ) + .file( + "benches/bench.rs", + r#" + #![feature(test)] + extern crate foo as the_foo; + extern crate test; + + #[bench] + fn foo(_b: &mut test::Bencher) { the_foo::bar(); } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "bar" + crate-type = ["dylib"] + "#, + ) + .file("bar/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("bench -v") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] [..] -C opt-level=3 [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] [..] -C opt-level=3 [..] +[RUNNING] [..] -C opt-level=3 [..] +[RUNNING] [..] -C opt-level=3 [..] +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[..]target/release/deps/foo-[HASH][EXE] --bench` +[RUNNING] `[..]target/release/deps/bench-[HASH][EXE] --bench` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.root().move_into_the_past(); + p.cargo("bench -v") + .with_stderr_data(str![[r#" +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[..]target/release/deps/foo-[HASH][EXE] --bench` +[RUNNING] `[..]target/release/deps/bench-[HASH][EXE] --bench` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_twice_with_build_cmd() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("build.rs", "fn main() {}") + .file( + "src/lib.rs", + " + #![feature(test)] + #[cfg(test)] + extern crate test; + #[bench] + fn foo(_b: &mut test::Bencher) {} + ", + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[FINISHED] `bench` profile [optimized] target(s) in [..] +[RUNNING] [..] (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_with_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "6.6.6" + edition = "2015" + authors = [] + + [[example]] + name = "teste1" + + [[bench]] + name = "testb1" + "#, + ) + .file( + "src/lib.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + #[cfg(test)] + use test::Bencher; + + pub fn f1() { + println!("f1"); + } + + pub fn f2() {} + + #[bench] + fn bench_bench1(_b: &mut Bencher) { + f2(); + } + "#, + ) + .file( + "benches/testb1.rs", + " + #![feature(test)] + extern crate foo; + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_bench2(_b: &mut Bencher) { + foo::f2(); + } + ", + ) + .file( + "examples/teste1.rs", + r#" + extern crate foo; + + fn main() { + println!("example1"); + foo::f1(); + } + "#, + ) + .build(); + + p.cargo("bench -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v6.6.6 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench` +[RUNNING] `[ROOT]/foo/target/release/deps/testb1-[HASH][EXE] --bench` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench_bench1 ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_bench2 ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn test_a_bench() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.1.0" + edition = "2015" + + [lib] + name = "foo" + test = false + doctest = false + + [[bench]] + name = "b" + test = true + "#, + ) + .file("src/lib.rs", "") + .file("benches/b.rs", "#[test] fn foo() {}") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] [..] (target/debug/deps/b-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn test_bench_no_run() { + let p = project() + .file("src/lib.rs", "") + .file( + "benches/bbaz.rs", + r#" + #![feature(test)] + + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_baz(_: &mut Bencher) {} + "#, + ) + .build(); + + p.cargo("bench --no-run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[EXECUTABLE] benches src/lib.rs (target/release/deps/foo-[HASH][EXE]) +[EXECUTABLE] benches/bbaz.rs (target/release/deps/bbaz-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn test_bench_no_run_emit_json() { + let p = project() + .file("src/lib.rs", "") + .file( + "benches/bbaz.rs", + r#" + #![feature(test)] + + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_baz(_: &mut Bencher) {} + "#, + ) + .build(); + + p.cargo("bench --no-run --message-format json") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn test_bench_no_fail_fast() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[bench] + fn bench_hello(_b: &mut test::Bencher) { + assert_eq!(hello(), "hello") + } + + #[bench] + fn bench_nope(_b: &mut test::Bencher) { + assert_eq!("nope", hello(), "NOPE!") + } + "#, + ) + .file( + "benches/b1.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] + fn b1_fail(_b: &mut test::Bencher) { assert_eq!(1, 2, "ONE=TWO"); } + "#, + ) + .build(); + + p.cargo("bench --no-fail-fast -- --test-threads=1") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/release/deps/foo-[HASH][EXE]) +[ERROR] bench failed, to rerun pass `--bin foo` +[RUNNING] benches/b1.rs (target/release/deps/b1-[HASH][EXE]) +[ERROR] bench failed, to rerun pass `--bench b1` +[ERROR] 2 targets failed: + `--bin foo` + `--bench b1` + +"#]]) + .with_stdout_data( + r#" +... +[..]NOPE![..] +... +[..]ONE=TWO[..] +... +"#, + ) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn test_bench_multiple_packages() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.1.0" + edition = "2015" + + [dependencies.bar] + path = "../bar" + + [dependencies.baz] + path = "../baz" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let _bar = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + authors = [] + version = "0.1.0" + edition = "2015" + + [[bench]] + name = "bbar" + test = true + "#, + ) + .file("src/lib.rs", "") + .file( + "benches/bbar.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_bar(_b: &mut Bencher) {} + "#, + ) + .build(); + + let _baz = project() + .at("baz") + .file( + "Cargo.toml", + r#" + [package] + name = "baz" + authors = [] + version = "0.1.0" + edition = "2015" + + [[bench]] + name = "bbaz" + test = true + "#, + ) + .file("src/lib.rs", "") + .file( + "benches/bbaz.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_baz(_b: &mut Bencher) {} + "#, + ) + .build(); + + p.cargo("bench -p bar -p baz") + .with_stderr_data(str![[r#" +[RUNNING] [..] (target/release/deps/bbaz-[HASH][EXE]) +[RUNNING] [..] (target/release/deps/bbar-[HASH][EXE]) + +"#]]) + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.1.0 ([ROOT]/bar) +[COMPILING] baz v0.1.0 ([ROOT]/baz) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE]) +[RUNNING] benches/bbar.rs (target/release/deps/bbar-[HASH][EXE]) +[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE]) +[RUNNING] benches/bbaz.rs (target/release/deps/bbaz-[HASH][EXE]) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_all_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "benches/foo.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_foo(_: &mut Bencher) -> () { () } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file( + "bar/benches/bar.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_bar(_: &mut Bencher) -> () { () } + "#, + ) + .build(); + + p.cargo("bench --workspace") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE]) +[RUNNING] benches/bar.rs (target/release/deps/bar-[HASH][EXE]) +[RUNNING] unittests src/main.rs (target/release/deps/foo-[HASH][EXE]) +[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_bar ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_foo ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_all_exclude() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file( + "bar/src/lib.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + #[bench] + pub fn bar(b: &mut test::Bencher) { + b.iter(|| {}); + } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file( + "baz/src/lib.rs", + "#[test] pub fn baz() { break_the_build(); }", + ) + .build(); + + p.cargo("bench --workspace --exclude baz") + .with_stdout_data(str![[r#" + +running 1 test +test bar ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_all_exclude_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file( + "bar/src/lib.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + #[bench] + pub fn bar(b: &mut test::Bencher) { + b.iter(|| {}); + } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file( + "baz/src/lib.rs", + "#[test] pub fn baz() { break_the_build(); }", + ) + .build(); + + p.cargo("bench --workspace --exclude '*z'") + .with_stdout_data(str![[r#" + +running 1 test +test bar ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_all_virtual_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file( + "bar/benches/bar.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_bar(_: &mut Bencher) -> () { () } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .file( + "baz/benches/baz.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_baz(_: &mut Bencher) -> () { () } + "#, + ) + .build(); + + // The order in which bar and baz are built is not guaranteed + p.cargo("bench --workspace") + .with_stderr_data( + str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE]) +[RUNNING] benches/bar.rs (target/release/deps/bar-[HASH][EXE]) +[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE]) +[RUNNING] benches/baz.rs (target/release/deps/baz-[HASH][EXE]) + +"#]] + .unordered(), + ) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_bar ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_baz ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_virtual_manifest_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() { break_the_build(); }") + .file( + "bar/benches/bar.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_bar(_: &mut Bencher) -> () { break_the_build(); } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .file( + "baz/benches/baz.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_baz(_: &mut Bencher) -> () { () } + "#, + ) + .build(); + + // This should not have `bar` built or benched + p.cargo("bench -p '*z'") + .with_stderr_data(str![[r#" +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE]) +[RUNNING] benches/baz.rs (target/release/deps/baz-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_baz ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +// https://github.com/rust-lang/cargo/issues/4287 +#[cargo_test(nightly, reason = "bench")] +fn legacy_bench_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [[bench]] + name = "bench" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/bench.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_foo(_: &mut Bencher) -> () { () } + "#, + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[WARNING] path `src/bench.rs` was erroneously implicitly accepted for benchmark `bench`, +please set bench.path in Cargo.toml +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/release/deps/foo-[HASH][EXE]) +[RUNNING] src/bench.rs (target/release/deps/bench-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_virtual_manifest_all_implied() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn foo() {}") + .file( + "bar/benches/bar.rs", + r#" + #![feature(test)] + extern crate test; + use test::Bencher; + #[bench] + fn bench_bar(_: &mut Bencher) -> () { () } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .file( + "baz/benches/baz.rs", + r#" + #![feature(test)] + extern crate test; + use test::Bencher; + #[bench] + fn bench_baz(_: &mut Bencher) -> () { () } + "#, + ) + .build(); + + // The order in which bar and baz are built is not guaranteed + + p.cargo("bench") + .with_stderr_data( + str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/release/deps/bar-[HASH][EXE]) +[RUNNING] benches/bar.rs (target/release/deps/bar-[HASH][EXE]) +[RUNNING] unittests src/lib.rs (target/release/deps/baz-[HASH][EXE]) +[RUNNING] benches/baz.rs (target/release/deps/baz-[HASH][EXE]) + +"#]] + .unordered(), + ) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_bar ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench_baz ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn json_artifact_includes_executable_for_benchmark() { + let p = project() + .file( + "benches/benchmark.rs", + r#" + #![feature(test)] + extern crate test; + + use test::Bencher; + + #[bench] + fn bench_foo(_: &mut Bencher) -> () { () } + "#, + ) + .build(); + + p.cargo("bench --no-run --message-format=json") + .with_stdout_data( + str![[r#" +[ + { + "executable": "[..]", + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "bin" + ], + "doc": false, + "doctest": false, + "edition": "2015", + "kind": [ + "bench" + ], + "name": "benchmark", + "src_path": "[ROOT]/foo/benches/benchmark.rs", + "test": false + } + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn cargo_bench_print_env_verbose() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.0.1")) + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[bench] + fn bench_hello(_b: &mut test::Bencher) { + assert_eq!(hello(), "hello") + } + "#, + ) + .build(); + p.cargo("bench -vv") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc[..]` +[FINISHED] `bench` profile [optimized] target(s) in [..] +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] [ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/binary_name.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/binary_name.rs new file mode 100644 index 000000000..a26ba9882 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/binary_name.rs @@ -0,0 +1,527 @@ +//! Tests for `cargo-features = ["different-binary-name"]`. + +use cargo_test_support::install::assert_has_installed_exe; +use cargo_test_support::install::assert_has_not_installed_exe; +use cargo_test_support::is_nightly; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn gated() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [[bin]] + name = "foo" + filename = "007bar" + path = "src/main.rs" + "#, + ) + .file("src/main.rs", "fn main() { assert!(true) }") + .build(); + + // Run cargo build. + p.cargo("build") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `different-binary-name` is required + + The package requires the Cargo feature called `different-binary-name`, but that feature is not stabilized in this version of Cargo ([..]). + Consider adding `cargo-features = ["different-binary-name"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#different-binary-name for more information about the status of this feature. + +"#]]) + .run(); +} + +#[cargo_test] +// This test checks if: +// 1. The correct binary is produced +// 2. The deps file has the correct content +// 3. Fingerprinting works +// 4. `cargo clean` command works +fn binary_name1() { + // Create the project. + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["different-binary-name"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [[bin]] + name = "foo" + filename = "007bar" + path = "src/main.rs" + "#, + ) + .file("src/main.rs", "fn main() { assert!(true) }") + .build(); + + // Run cargo build. + p.cargo("build") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .run(); + + // Check the name of the binary that cargo has generated. + // A binary with the name of the crate should NOT be created. + let foo_path = p.bin("foo"); + assert!(!foo_path.is_file()); + // A binary with the name provided in `filename` parameter should be created. + let bar_path = p.bin("007bar"); + assert!(bar_path.is_file()); + + // Check if deps file exists. + let deps_path = p.bin("007bar").with_extension("d"); + assert!(deps_path.is_file(), "{:?}", bar_path); + + let depinfo = p.read_file(&deps_path); + + // Prepare what content we expect to be present in deps file. + let deps_exp = format!( + "{}: {}", + p.bin("007bar").to_str().unwrap(), + p.root().join("src").join("main.rs").to_str().unwrap() + ); + + // Compare actual deps content with expected deps content. + assert!( + depinfo.lines().any(|line| line == deps_exp), + "Content of `{}` is incorrect", + deps_path.to_string_lossy() + ); + + // Run cargo second time, to verify fingerprint. + p.cargo("build -p foo -v") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Run cargo clean. + p.cargo("clean -p foo") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .run(); + + // Check if the appropriate file was removed. + assert!( + !bar_path.is_file(), + "`cargo clean` did not remove the correct files" + ); +} + +#[cargo_test] +// This test checks if: +// 1. Check `cargo run` +// 2. Check `cargo test` +// 3. Check `cargo install/uninstall` +fn binary_name2() { + // Create the project. + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["different-binary-name"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [[bin]] + name = "foo" + filename = "007bar" + "#, + ) + .file( + "src/main.rs", + r#" + fn hello(name: &str) -> String { + format!("Hello, {}!", name) + } + + fn main() { + println!("{}", hello("crabs")); + } + + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn check_crabs() { + assert_eq!(hello("crabs"), "Hello, crabs!"); + } + } + "#, + ) + .build(); + + // Run cargo build. + p.cargo("build") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .run(); + + // Check the name of the binary that cargo has generated. + // A binary with the name of the crate should NOT be created. + let foo_path = p.bin("foo"); + assert!(!foo_path.is_file()); + // A binary with the name provided in `filename` parameter should be created. + let bar_path = p.bin("007bar"); + assert!(bar_path.is_file()); + + // Check if `cargo test` works + p.cargo("test") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[..][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test tests::check_crabs ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + // Check if `cargo run` is able to execute the binary + p.cargo("run") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .with_stdout_data(str![[r#" +Hello, crabs! + +"#]]) + .run(); + + p.cargo("install") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .run(); + + assert_has_installed_exe(paths::cargo_home(), "007bar"); + + p.cargo("uninstall") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/007bar[EXE] + +"#]]) + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .run(); + + assert_has_not_installed_exe(paths::cargo_home(), "007bar"); +} + +#[cargo_test] +fn check_env_vars() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["different-binary-name"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [[bin]] + name = "foo" + filename = "007bar" + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{}", option_env!("CARGO_BIN_NAME").unwrap()); + } + "#, + ) + .file( + "tests/integration.rs", + r#" + #[test] + fn check_env_vars2() { + let value = option_env!("CARGO_BIN_EXE_007bar").expect("Could not find environment variable."); + assert!(value.contains("007bar")); + } + "# + ) + .build(); + + // Run cargo build. + p.cargo("build") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .run(); + p.cargo("run") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .with_stdout_data(str![[r#" +007bar + +"#]]) + .run(); + p.cargo("test") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .with_status(0) + .run(); +} + +#[cargo_test] +fn check_msg_format_json() { + // Create the project. + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["different-binary-name"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [[bin]] + name = "foo" + filename = "007bar" + path = "src/main.rs" + "#, + ) + .file("src/main.rs", "fn main() { assert!(true) }") + .build(); + + // Run cargo build. + p.cargo("build --message-format=json") + .masquerade_as_nightly_cargo(&["different-binary-name"]) + .with_stdout_data( + str![[r#" +[ + { + "executable": "[ROOT]/foo/target/debug/007bar[EXE]", + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": "{...}" + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn targets_with_relative_path_in_workspace_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["relative-bar"] + resolver = "2" + "#, + ) + .file( + "relative-bar/Cargo.toml", + r#" + [package] + name = "relative-bar" + version = "0.1.0" + edition = "2021" + + build = "./build.rs" + + [[bin]] + name = "bar" + path = "./src/main.rs" + + [lib] + name = "lib" + path = "./src/lib.rs" + + [[example]] + name = "example" + path = "./example.rs" + + [[test]] + name = "test" + path = "./test.rs" + + [[bench]] + name = "bench" + path = "./bench.rs" + "#, + ) + .file("relative-bar/build.rs", "fn main() { let a = 1; }") + .file("relative-bar/src/main.rs", "fn main() { let a = 1; }") + .file("relative-bar/src/lib.rs", "fn a() {}") + .file("relative-bar/example.rs", "fn main() { let a = 1; }") + .file( + "relative-bar/test.rs", + r#" + fn main() {} + + #[test] + fn test_a() { let a = 1; } + "#, + ) + .file( + "relative-bar/bench.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + #[bench] + fn bench_a(_b: &mut test::Bencher) { let a = 1; } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +... + --> relative-bar/build.rs:1:17 +... + --> relative-bar/src/lib.rs:1:4 +... + --> relative-bar/src/main.rs:1:17 +... +"#]]) + .run(); + + p.cargo("check --example example") + .with_stderr_data(str![[r#" +... + --> relative-bar/example.rs:1:17 +... +"#]]) + .run(); + + p.cargo("check --test test") + .with_stderr_data(str![[r#" +... + --> relative-bar/test.rs:5:35 +... +"#]]) + .run(); + + if is_nightly() { + p.cargo("check --bench bench") + .with_stderr_data(str![[r#" +... + --> relative-bar/bench.rs:7:58 +... +"#]]) + .run(); + } + + // Disable Cargo target auto-discovery. + p.change_file( + "relative-bar/Cargo.toml", + r#" + [package] + name = "relative-bar" + version = "0.1.0" + edition = "2021" + + autolib = false + autobins = false + autoexamples = false + autotests = false + autobenches = false + + build = "./build.rs" + + [[bin]] + name = "bar" + path = "./src/main.rs" + + [lib] + name = "lib" + path = "./src/lib.rs" + + [[example]] + name = "example" + path = "./example.rs" + + [[test]] + name = "test" + path = "./test.rs" + + [[bench]] + name = "bench" + path = "./bench.rs" + "#, + ); + + p.cargo("check") + .with_stderr_data(str![[r#" +... + --> relative-bar/build.rs:1:17 +... + --> relative-bar/src/lib.rs:1:4 +... + --> relative-bar/src/main.rs:1:17 +... +"#]]) + .run(); + + p.cargo("check --example example") + .with_stderr_data(str![[r#" +... + --> relative-bar/example.rs:1:17 +... +"#]]) + .run(); + + p.cargo("check --test test") + .with_stderr_data(str![[r#" +... + --> relative-bar/test.rs:5:35 +... +"#]]) + .run(); + + if is_nightly() { + p.cargo("check --bench bench") + .with_stderr_data(str![[r#" +... + --> relative-bar/bench.rs:7:58 +... +"#]]) + .run(); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build.rs new file mode 100644 index 000000000..561b9b4ad --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build.rs @@ -0,0 +1,6749 @@ +//! Tests for the `cargo build` command. + +use std::env; +use std::fs; +use std::io::Read; +use std::process::Stdio; + +use cargo::{ + core::compiler::CompileMode, + core::{Shell, Workspace}, + ops::CompileOptions, + GlobalContext, +}; +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::paths::root; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{ + basic_bin_manifest, basic_lib_manifest, basic_manifest, cargo_exe, cargo_process, git, + is_nightly, main_file, paths, process, project, rustc_host, sleep_ms, symlink_supported, t, + tools, Execs, ProjectBuilder, +}; +use cargo_util::paths::dylib_path_envvar; + +#[cargo_test] +fn cargo_compile_simple() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +i am foo + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_symlink_to_path_dependency_with_build_script_in_git() { + if !symlink_supported() { + return; + } + + let root = paths::root(); + git::repo(&root) + .nocommit_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + # the path leads through a symlink, 'symlink-to-original' is a worktree root, + # and symlink-to-dir/ is a symlink to a sub-directory to be stepped through. + lib = { version = "0.1.0", path = "symlink-to-original/symlink-to-dir/lib" } + "#, + ) + .nocommit_file("src/main.rs", "fn main() { }") + .nocommit_file("original/dir/lib/build.rs", "fn main() {}") + .nocommit_file( + "original/dir/lib/Cargo.toml", + r#" + [package] + name = "lib" + version = "0.1.0" + edition = "2021" + "#, + ) + .nocommit_file("original/dir/lib/src/lib.rs", "") + .nocommit_symlink_dir("original", "symlink-to-original") + .nocommit_symlink_dir("original/dir", "original/symlink-to-dir") + .build(); + + // It is necessary to have a sub-repository and to add files so there is an index. + let repo = git::init(&root.join("original")); + git::add(&repo); + cargo_process("build").run(); +} + +#[cargo_test] +fn cargo_fail_with_no_stderr() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", &String::from("refusal")) + .build(); + p.cargo("build --message-format=json") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); +} + +/// Checks that the `CARGO_INCREMENTAL` environment variable results in +/// `rustc` getting `-C incremental` passed to it. +#[cargo_test] +fn cargo_compile_incremental() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build -v") + .env("CARGO_INCREMENTAL", "1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C incremental=[ROOT]/foo/target/debug/incremental[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test -v") + .env("CARGO_INCREMENTAL", "1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C incremental=[ROOT]/foo/target/debug/incremental[..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn incremental_profile() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [profile.dev] + incremental = false + + [profile.release] + incremental = true + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .env_remove("CARGO_INCREMENTAL") + .with_stderr_does_not_contain("[..]C incremental=[..]") + .run(); + + p.cargo("build -v") + .env("CARGO_INCREMENTAL", "1") + .with_stderr_contains("[..]C incremental=[..]") + .run(); + + p.cargo("build --release -v") + .env_remove("CARGO_INCREMENTAL") + .with_stderr_contains("[..]C incremental=[..]") + .run(); + + p.cargo("build --release -v") + .env("CARGO_INCREMENTAL", "0") + .with_stderr_does_not_contain("[..]C incremental=[..]") + .run(); +} + +#[cargo_test] +fn incremental_config() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [build] + incremental = false + "#, + ) + .build(); + + p.cargo("build -v") + .env_remove("CARGO_INCREMENTAL") + .with_stderr_does_not_contain("[..]C incremental=[..]") + .run(); + + p.cargo("build -v") + .env("CARGO_INCREMENTAL", "1") + .with_stderr_contains("[..]C incremental=[..]") + .run(); +} + +#[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_data(str![[r#" +[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_unsupported_short_config_flag() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build -c net.git-fetch-with-cli=true") + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '-c' found + + tip: a similar argument exists: '--config' + +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(); + + p.cargo("build --workspace --exclude foo") + .with_stderr_data(str![[r#" +[ERROR] no packages to compile + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn cargo_compile_manifest_path() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build --manifest-path foo/Cargo.toml") + .cwd(p.root().parent().unwrap()) + .run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn cargo_compile_with_wrong_manifest_path_flag() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build --path foo/Cargo.toml") + .cwd(p.root().parent().unwrap()) + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '--path' found + + tip: a similar argument exists: '--manifest-path' + +Usage: cargo[EXE] build [OPTIONS] + +For more information, try '--help'. + +"#]]) + .with_status(1) + .run(); +} + +#[cargo_test] +fn chdir_gated() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .build(); + p.cargo("-C foo build") + .cwd(p.root().parent().unwrap()) + .with_stderr_data(str![[r#" +[ERROR] the `-C` flag is unstable, pass `-Z unstable-options` on the nightly channel to enable it + +"#]]) + .with_status(101) + .run(); + // No masquerade should also fail. + p.cargo("-C foo -Z unstable-options build") + .cwd(p.root().parent().unwrap()) + .with_stderr_data(str![[r#" +[ERROR] the `-C` flag is unstable, pass `-Z unstable-options` on the nightly channel to enable it + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn cargo_compile_directory_not_cwd() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .file(".cargo/config.toml", &"") + .build(); + + p.cargo("-Zunstable-options -C foo build") + .masquerade_as_nightly_cargo(&["chdir"]) + .cwd(p.root().parent().unwrap()) + .run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn cargo_compile_with_unsupported_short_unstable_feature_flag() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .file(".cargo/config.toml", &"") + .build(); + + p.cargo("-zunstable-options -C foo build") + .masquerade_as_nightly_cargo(&["chdir"]) + .cwd(p.root().parent().unwrap()) + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '-z' found + + tip: a similar argument exists: '-Z' + +Usage: cargo [..][OPTIONS] [COMMAND] + cargo [..][OPTIONS] -Zscript [ARGS]... + +For more information, try '--help'. + +"#]]) + .with_status(1) + .run(); +} + +#[cargo_test] +fn cargo_compile_directory_not_cwd_with_invalid_config() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .file(".cargo/config.toml", &"!") + .build(); + + p.cargo("-Zunstable-options -C foo build") + .masquerade_as_nightly_cargo(&["chdir"]) + .cwd(p.root().parent().unwrap()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not load Cargo configuration + +Caused by: + could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml` + +Caused by: + TOML parse error at line 1, column 1 + | + 1 | ! + | ^ + invalid key + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_manifest() { + let p = project().file("Cargo.toml", "").build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + manifest is missing either a `[package]` or a `[workspace]` + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_manifest2() { + let p = project() + .file( + "Cargo.toml", + " + [package] + foo = bar + ", + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid string +expected `"`, `'` + --> Cargo.toml:3:23 + | +3 | foo = bar + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_manifest3() { + let p = project().file("src/Cargo.toml", "a = bar").build(); + + p.cargo("build --manifest-path src/Cargo.toml") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid string +expected `"`, `'` + --> src/Cargo.toml:1:5 + | +1 | a = bar + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_duplicate_build_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "main" + path = "src/main.rs" + crate-type = ["dylib"] + + [dependencies] + "#, + ) + .file("src/main.rs", "#![allow(warnings)] fn main() {}") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] file `[ROOT]/foo/src/main.rs` found to be present in multiple build targets: + * `lib` target `main` + * `bin` target `foo` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_version() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0")) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected end of input while parsing minor version number + --> Cargo.toml:4:19 + | +4 | version = "1.0" + | ^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_empty_package_name() { + let p = project() + .file("Cargo.toml", &basic_manifest("", "0.0.0")) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package name cannot be empty + --> Cargo.toml:3:16 + | +3 | name = "" + | ^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_package_name() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo@bar", "0.0.0")) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character `@` in package name: `foo@bar`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) + --> Cargo.toml:3:16 + | +3 | name = "foo@bar" + | ^^^^^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_bin_target_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [[bin]] + name = "" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + binary target names cannot be empty + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_forbidden_bin_target_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [[bin]] + name = "build" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the binary target name `build` is forbidden, it conflicts with cargo's build directory names + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_bin_and_crate_type() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [[bin]] + name = "the_foo_bin" + path = "src/foo.rs" + crate-type = ["cdylib", "rlib"] + "#, + ) + .file("src/foo.rs", "fn main() {}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the target `the_foo_bin` is a binary and can't have any crate-types set (currently "cdylib, rlib") + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_api_exposes_artifact_paths() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [[bin]] + name = "the_foo_bin" + path = "src/bin.rs" + + [lib] + name = "the_foo_lib" + path = "src/foo.rs" + crate-type = ["cdylib", "rlib"] + "#, + ) + .file("src/foo.rs", "pub fn bar() {}") + .file("src/bin.rs", "pub fn main() {}") + .build(); + + let shell = Shell::from_write(Box::new(Vec::new())); + let gctx = GlobalContext::new(shell, env::current_dir().unwrap(), paths::home()); + let ws = Workspace::new(&p.root().join("Cargo.toml"), &gctx).unwrap(); + let compile_options = CompileOptions::new(ws.gctx(), CompileMode::Build).unwrap(); + + let result = cargo::ops::compile(&ws, &compile_options).unwrap(); + + assert_eq!(1, result.binaries.len()); + assert!(result.binaries[0].path.exists()); + assert!(result.binaries[0] + .path + .to_str() + .unwrap() + .contains("the_foo_bin")); + + assert_eq!(1, result.cdylibs.len()); + // The exact library path varies by platform, but should certainly exist at least + assert!(result.cdylibs[0].path.exists()); + assert!(result.cdylibs[0] + .path + .to_str() + .unwrap() + .contains("the_foo_lib")); +} + +#[cargo_test] +fn cargo_compile_with_bin_and_proc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [[bin]] + name = "the_foo_bin" + path = "src/foo.rs" + proc-macro = true + "#, + ) + .file("src/foo.rs", "fn main() {}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the target `the_foo_bin` is a binary and can't have `proc-macro` set `true` + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_lib_target_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [lib] + name = "" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + library target names cannot be empty + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_non_numeric_dep_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + crossbeam = "y" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse the version requirement `y` for dependency `crossbeam` + +Caused by: + unexpected character 'y' while parsing major version number + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_without_manifest() { + let p = project().no_manifest().build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not find `Cargo.toml` in `[ROOT]/foo` or any parent directory + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(target_os = "linux")] +fn cargo_compile_with_lowercase_cargo_toml() { + let p = project() + .no_manifest() + .file("cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not find `Cargo.toml` in `[ROOT]/foo` or any parent directory, but found cargo.toml please try to rename it to Cargo.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_invalid_code() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "invalid rust code!") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[ERROR] [..] +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); + assert!(p.root().join("Cargo.lock").is_file()); +} + +#[cargo_test] +fn cargo_compile_with_invalid_code_in_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + [dependencies.baz] + path = "../baz" + "#, + ) + .file("src/main.rs", "invalid rust code!") + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "invalid rust code!") + .build(); + let _baz = project() + .at("baz") + .file("Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("src/lib.rs", "invalid rust code!") + .build(); + p.cargo("build") + .with_status(101) + .with_stderr_data( + str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/bar) +[COMPILING] baz v0.1.0 ([ROOT]/baz) +[ERROR] could not compile `bar` (lib) due to 1 previous error +[ERROR] could not compile `baz` (lib) due to 1 previous error +... + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_warnings_in_the_root_package() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {} fn dead() {}") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[WARNING] [..]dead[..] +... +[WARNING] `foo` (bin "foo") generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_warnings_in_a_dep_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + + [[bin]] + + name = "foo" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file( + "bar/src/bar.rs", + r#" + pub fn gimme() -> &'static str { + "test passed" + } + + fn dead() {} + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[WARNING] [..]dead[..] +... +[WARNING] `bar` (lib) generated 1 warning +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +test passed + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_nested_deps_inferred() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = 'bar' + + [[bin]] + name = "foo" + "#, + ) + .file("src/foo.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.baz] + path = "../baz" + "#, + ) + .file( + "bar/src/lib.rs", + r#" + extern crate baz; + + pub fn gimme() -> String { + baz::gimme() + } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.5.0")) + .file( + "baz/src/lib.rs", + r#" + pub fn gimme() -> String { + "test passed".to_string() + } + "#, + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + assert!(!p.bin("libbar.rlib").is_file()); + assert!(!p.bin("libbaz.rlib").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +test passed + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_nested_deps_correct_bin() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.baz] + path = "../baz" + "#, + ) + .file( + "bar/src/lib.rs", + r#" + extern crate baz; + + pub fn gimme() -> String { + baz::gimme() + } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.5.0")) + .file( + "baz/src/lib.rs", + r#" + pub fn gimme() -> String { + "test passed".to_string() + } + "#, + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + assert!(!p.bin("libbar.rlib").is_file()); + assert!(!p.bin("libbaz.rlib").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +test passed + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_nested_deps_shorthand() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.baz] + path = "../baz" + + [lib] + + name = "bar" + "#, + ) + .file( + "bar/src/bar.rs", + r#" + extern crate baz; + + pub fn gimme() -> String { + baz::gimme() + } + "#, + ) + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file( + "baz/src/baz.rs", + r#" + pub fn gimme() -> String { + "test passed".to_string() + } + "#, + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + assert!(!p.bin("libbar.rlib").is_file()); + assert!(!p.bin("libbaz.rlib").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +test passed + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_nested_deps_longhand() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + version = "0.5.0" + edition = "2015" + + [[bin]] + + name = "foo" + "#, + ) + .file("src/foo.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.baz] + path = "../baz" + version = "0.5.0" + edition = "2015" + + [lib] + + name = "bar" + "#, + ) + .file( + "bar/src/bar.rs", + r#" + extern crate baz; + + pub fn gimme() -> String { + baz::gimme() + } + "#, + ) + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file( + "baz/src/baz.rs", + r#" + pub fn gimme() -> String { + "test passed".to_string() + } + "#, + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + assert!(!p.bin("libbar.rlib").is_file()); + assert!(!p.bin("libbaz.rlib").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +test passed + +"#]]) + .run(); +} + +// Check that Cargo gives a sensible error if a dependency can't be found +// because of a name mismatch. +#[cargo_test] +fn cargo_compile_with_dep_name_mismatch() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.0.1" + edition = "2015" + authors = ["wycats@example.com"] + + [[bin]] + + name = "foo" + + [dependencies.notquitebar] + + path = "bar" + "#, + ) + .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &["bar"])) + .file("bar/Cargo.toml", &basic_bin_manifest("bar")) + .file("bar/src/bar.rs", &main_file(r#""i am bar""#, &[])) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no matching package named `notquitebar` found +location searched: [ROOT]/foo/bar +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]) + .run(); +} + +// Ensure that renamed deps have a valid name +#[cargo_test] +fn cargo_compile_with_invalid_dep_rename() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "buggin" + version = "0.1.0" + edition = "2015" + + [dependencies] + "haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } + "#, + ) + .file("src/main.rs", &main_file(r#""What's good?""#, &[])) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character ` ` in package name: `haha this isn't a valid name 🐛`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) + --> Cargo.toml:8:17 + | +8 | "haha this isn't a valid name 🐛" = { package = "libc", version = "0.1" } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_filename() { + let p = project() + .file("src/lib.rs", "") + .file( + "src/bin/a.rs", + r#" + extern crate foo; + fn main() { println!("hello a.rs"); } + "#, + ) + .file("examples/a.rs", r#"fn main() { println!("example"); }"#) + .build(); + + p.cargo("build --bin bin.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no bin target named `bin.rs`. +Available bin targets: + a + + +"#]]) + .run(); + + p.cargo("build --bin a.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no bin target named `a.rs` + +[HELP] a target with a similar name exists: `a` + +"#]]) + .run(); + + p.cargo("build --example example.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target named `example.rs`. +Available example targets: + a + + +"#]]) + .run(); + + p.cargo("build --example a.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target named `a.rs` + +[HELP] a target with a similar name exists: `a` + +"#]]) + .run(); +} + +#[cargo_test] +fn incompatible_dependencies() { + Package::new("bad", "0.1.0").publish(); + Package::new("bad", "1.0.0").publish(); + Package::new("bad", "1.0.1").publish(); + Package::new("bad", "1.0.2").publish(); + Package::new("bar", "0.1.0").dep("bad", "0.1.0").publish(); + Package::new("baz", "0.1.1").dep("bad", "=1.0.0").publish(); + Package::new("baz", "0.1.0").dep("bad", "=1.0.0").publish(); + Package::new("qux", "0.1.2").dep("bad", ">=1.0.1").publish(); + Package::new("qux", "0.1.1").dep("bad", ">=1.0.1").publish(); + Package::new("qux", "0.1.0").dep("bad", ">=1.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.1.0" + baz = "0.1.0" + qux = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for `bad`. + ... required by package `qux v0.1.0` + ... which satisfies dependency `qux = "^0.1.0"` of package `foo v0.0.1 ([ROOT]/foo)` +versions that meet the requirements `>=1.0.1` are: 1.0.2, 1.0.1 + +all possible versions conflict with previously selected packages. + + previously selected package `bad v1.0.0` + ... which satisfies dependency `bad = "=1.0.0"` of package `baz v0.1.0` + ... which satisfies dependency `baz = "^0.1.0"` of package `foo v0.0.1 ([ROOT]/foo)` + +failed to select a version for `bad` which could resolve this conflict + +"#]]) + .run(); +} + +#[cargo_test] +fn incompatible_dependencies_with_multi_semver() { + Package::new("bad", "1.0.0").publish(); + Package::new("bad", "1.0.1").publish(); + Package::new("bad", "2.0.0").publish(); + Package::new("bad", "2.0.1").publish(); + Package::new("bar", "0.1.0").dep("bad", "=1.0.0").publish(); + Package::new("baz", "0.1.0").dep("bad", ">=2.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.1.0" + baz = "0.1.0" + bad = ">=1.0.1, <=2.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for `bad`. + ... required by package `foo v0.0.1 ([ROOT]/foo)` +versions that meet the requirements `>=1.0.1, <=2.0.0` are: 2.0.0, 1.0.1 + +all possible versions conflict with previously selected packages. + + previously selected package `bad v2.0.1` + ... which satisfies dependency `bad = ">=2.0.1"` of package `baz v0.1.0` + ... which satisfies dependency `baz = "^0.1.0"` of package `foo v0.0.1 ([ROOT]/foo)` + + previously selected package `bad v1.0.0` + ... which satisfies dependency `bad = "=1.0.0"` of package `bar v0.1.0` + ... which satisfies dependency `bar = "^0.1.0"` of package `foo v0.0.1 ([ROOT]/foo)` + +failed to select a version for `bad` which could resolve this conflict + +"#]]) + .run(); +} + +#[cargo_test] +fn compile_path_dep_then_change_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.0.2")); + + p.cargo("build").run(); +} + +#[cargo_test] +fn ignores_carriage_return_in_lockfile() { + let p = project() + .file("src/main.rs", "mod a; fn main() {}") + .file("src/a.rs", "") + .build(); + + p.cargo("build").run(); + + let lock = p.read_lockfile(); + p.change_file("Cargo.lock", &lock.replace("\n", "\r\n")); + p.cargo("build").run(); +} + +#[cargo_test] +fn cargo_default_env_metadata_env_var() { + // Ensure that path dep + dylib + env_var get metadata + // (even though path_dep + dylib should not) + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/lib.rs", "// hi") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "bar" + crate-type = ["dylib"] + "#, + ) + .file("bar/src/lib.rs", "// hello") + .build(); + + let dll_prefix = env::consts::DLL_PREFIX; + let dll_suffix = env::consts::DLL_SUFFIX; + + // No metadata on libbar since it's a dylib path dependency + p.cargo("build -v") + .with_stderr_data(format!( + "\ +... +[RUNNING] `rustc --crate-name foo [..]--extern bar=[ROOT]/foo/target/debug/deps/{dll_prefix}bar{dll_suffix}` +... +")) + .run(); + + p.cargo("clean").run(); + + // If you set the env-var, then we expect metadata on libbar + p.cargo("build -v") + .env("__CARGO_DEFAULT_LIB_METADATA", "stable") + .with_stderr_data(format!( + "\ +... +[RUNNING] `rustc --crate-name foo [..]--extern bar=[ROOT]/foo/target/debug/deps/{dll_prefix}bar-[..]{dll_suffix}` +... +")) + .run(); +} + +#[cargo_test] +fn crate_env_vars() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.1-alpha.1" + edition = "2015" + description = "This is foo" + homepage = "https://example.com" + repository = "https://example.com/repo.git" + authors = ["wycats@example.com"] + license = "MIT OR Apache-2.0" + license-file = "license.txt" + rust-version = "1.61.0" + readme = "../../README.md" + + [[bin]] + name = "foo-bar" + path = "src/main.rs" + "#, + ) + .file( + "src/main.rs", + r#" + extern crate foo; + + + static VERSION_MAJOR: &'static str = env!("CARGO_PKG_VERSION_MAJOR"); + static VERSION_MINOR: &'static str = env!("CARGO_PKG_VERSION_MINOR"); + static VERSION_PATCH: &'static str = env!("CARGO_PKG_VERSION_PATCH"); + static VERSION_PRE: &'static str = env!("CARGO_PKG_VERSION_PRE"); + static VERSION: &'static str = env!("CARGO_PKG_VERSION"); + static CARGO_MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR"); + static CARGO_MANIFEST_PATH: &'static str = env!("CARGO_MANIFEST_PATH"); + static PKG_NAME: &'static str = env!("CARGO_PKG_NAME"); + static HOMEPAGE: &'static str = env!("CARGO_PKG_HOMEPAGE"); + static REPOSITORY: &'static str = env!("CARGO_PKG_REPOSITORY"); + static LICENSE: &'static str = env!("CARGO_PKG_LICENSE"); + static LICENSE_FILE: &'static str = env!("CARGO_PKG_LICENSE_FILE"); + static DESCRIPTION: &'static str = env!("CARGO_PKG_DESCRIPTION"); + static RUST_VERSION: &'static str = env!("CARGO_PKG_RUST_VERSION"); + static README: &'static str = env!("CARGO_PKG_README"); + static BIN_NAME: &'static str = env!("CARGO_BIN_NAME"); + static CRATE_NAME: &'static str = env!("CARGO_CRATE_NAME"); + + + fn main() { + let s = format!("{}-{}-{} @ {} in {} file {}", VERSION_MAJOR, + VERSION_MINOR, VERSION_PATCH, VERSION_PRE, + CARGO_MANIFEST_DIR, CARGO_MANIFEST_PATH); + assert_eq!(s, foo::version()); + println!("{}", s); + assert_eq!("foo", PKG_NAME); + assert_eq!("foo-bar", BIN_NAME); + assert_eq!("foo_bar", CRATE_NAME); + assert_eq!("https://example.com", HOMEPAGE); + assert_eq!("https://example.com/repo.git", REPOSITORY); + assert_eq!("MIT OR Apache-2.0", LICENSE); + assert_eq!("license.txt", LICENSE_FILE); + assert_eq!("This is foo", DESCRIPTION); + assert_eq!("1.61.0", RUST_VERSION); + assert_eq!("../../README.md", README); + let s = format!("{}.{}.{}-{}", VERSION_MAJOR, + VERSION_MINOR, VERSION_PATCH, VERSION_PRE); + assert_eq!(s, VERSION); + + // Verify CARGO_TARGET_TMPDIR isn't set for bins + assert!(option_env!("CARGO_TARGET_TMPDIR").is_none()); + } + "#, + ) + .file( + "src/lib.rs", + r#" + use std::env; + use std::path::PathBuf; + + pub fn version() -> String { + format!("{}-{}-{} @ {} in {} file {}", + env!("CARGO_PKG_VERSION_MAJOR"), + env!("CARGO_PKG_VERSION_MINOR"), + env!("CARGO_PKG_VERSION_PATCH"), + env!("CARGO_PKG_VERSION_PRE"), + env!("CARGO_MANIFEST_DIR"), + env!("CARGO_MANIFEST_PATH")) + } + + pub fn check_no_int_test_env() { + env::var("CARGO_TARGET_DIR").unwrap_err(); + } + + pub fn check_tmpdir(tmp: Option<&'static str>) { + let tmpdir: PathBuf = tmp.unwrap().into(); + + let exe: PathBuf = env::current_exe().unwrap().into(); + let mut expected: PathBuf = exe.parent().unwrap() + .parent().unwrap() + .parent().unwrap() + .into(); + expected.push("tmp"); + assert_eq!(tmpdir, expected); + + // Check that CARGO_TARGET_TMPDIR isn't set for lib code + assert!(option_env!("CARGO_TARGET_TMPDIR").is_none()); + env::var("CARGO_TARGET_TMPDIR").unwrap_err(); + } + + #[test] + fn unit_env_cargo_target_tmpdir() { + // Check that CARGO_TARGET_TMPDIR isn't set for unit tests + assert!(option_env!("CARGO_TARGET_TMPDIR").is_none()); + env::var("CARGO_TARGET_TMPDIR").unwrap_err(); + } + "#, + ) + .file( + "examples/ex-env-vars.rs", + r#" + static PKG_NAME: &'static str = env!("CARGO_PKG_NAME"); + static BIN_NAME: &'static str = env!("CARGO_BIN_NAME"); + static CRATE_NAME: &'static str = env!("CARGO_CRATE_NAME"); + + fn main() { + assert_eq!("foo", PKG_NAME); + assert_eq!("ex-env-vars", BIN_NAME); + assert_eq!("ex_env_vars", CRATE_NAME); + + // Verify CARGO_TARGET_TMPDIR isn't set for examples + assert!(option_env!("CARGO_TARGET_TMPDIR").is_none()); + } + "#, + ) + .file( + "tests/env.rs", + r#" + #[test] + fn integration_env_cargo_target_tmpdir() { + foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR")); + } + "#, + ); + + let p = if is_nightly() { + p.file( + "benches/env.rs", + r#" + #![feature(test)] + extern crate test; + use test::Bencher; + + #[bench] + fn bench_env_cargo_target_tmpdir(_: &mut Bencher) { + foo::check_tmpdir(option_env!("CARGO_TARGET_TMPDIR")); + } + "#, + ) + .build() + } else { + p.build() + }; + + println!("build"); + p.cargo("build -v").run(); + + println!("bin"); + p.process(&p.bin("foo-bar")) + .with_stdout_data(str![[r#" +0-5-1 @ alpha.1 in [ROOT]/foo file [ROOT]/foo/Cargo.toml + +"#]]) + .run(); + + println!("example"); + p.cargo("run --example ex-env-vars -v").run(); + + println!("test"); + p.cargo("test -v").run(); + + if is_nightly() { + println!("bench"); + p.cargo("bench -v").run(); + } +} + +#[cargo_test] +fn crate_authors_env_vars() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.1-alpha.1" + edition = "2015" + authors = ["wycats@example.com", "neikos@example.com"] + "#, + ) + .file( + "src/main.rs", + r#" + extern crate foo; + + static AUTHORS: &'static str = env!("CARGO_PKG_AUTHORS"); + + fn main() { + let s = "wycats@example.com:neikos@example.com"; + assert_eq!(AUTHORS, foo::authors()); + println!("{}", AUTHORS); + assert_eq!(s, AUTHORS); + } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn authors() -> String { + format!("{}", env!("CARGO_PKG_AUTHORS")) + } + "#, + ) + .build(); + + println!("build"); + p.cargo("build -v").run(); + + println!("bin"); + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +wycats@example.com:neikos@example.com + +"#]]) + .run(); + + println!("test"); + p.cargo("test -v").run(); +} + +#[cargo_test] +fn vv_prints_rustc_env_vars() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = ["escape='\"@example.com"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + let mut b = p.cargo("build -vv"); + + #[cfg(windows)] + { + b.with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] CARGO_PKG_AUTHORS="escape='/"@example.com"&& [..] set CARGO_PKG_NAME=foo&& [..] rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } + + #[cfg(not(windows))] + { + b.with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] CARGO_PKG_AUTHORS='escape='/''"@example.com' [..] CARGO_PKG_NAME=foo [..] rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } + + b.run(); +} + +// The tester may already have LD_LIBRARY_PATH=::/foo/bar which leads to a false positive error +fn setenv_for_removing_empty_component(mut execs: Execs) -> Execs { + let v = dylib_path_envvar(); + if let Ok(search_path) = env::var(v) { + let new_search_path = + env::join_paths(env::split_paths(&search_path).filter(|e| !e.as_os_str().is_empty())) + .expect("join_paths"); + execs.env(v, new_search_path); // build_command() will override LD_LIBRARY_PATH accordingly + } + execs +} + +// Regression test for #4277 +#[cargo_test] +fn crate_library_path_env_var() { + let p = project() + .file( + "src/main.rs", + &format!( + r#" + fn main() {{ + let search_path = env!("{}"); + let paths = std::env::split_paths(&search_path).collect::>(); + assert!(!paths.contains(&"".into())); + }} + "#, + dylib_path_envvar() + ), + ) + .build(); + + setenv_for_removing_empty_component(p.cargo("run")).run(); +} + +// See https://github.com/rust-lang/cargo/issues/14194 +#[cargo_test] +fn issue_14194_deduplicate_library_path_env_var() { + let p = project() + .file( + "src/main.rs", + &format!( + r#" + use std::process::Command; + fn main() {{ + let level: i32 = std::env::args().nth(1).unwrap().parse().unwrap(); + let txt = "var.txt"; + let lib_path = std::env::var("{}").unwrap(); + + // Make sure we really have something in dylib search path. + let count = std::env::split_paths(&lib_path).count(); + assert!(count > 0); + + if level >= 3 {{ + std::fs::write(txt, &lib_path).unwrap(); + }} else {{ + let prev_lib_path = std::fs::read_to_string(txt).unwrap(); + // Ensure no duplicate insertion to dylib search paths + // when calling `cargo run` recursively. + assert_eq!(lib_path, prev_lib_path); + }} + + if level == 0 {{ + return; + }} + + let _ = Command::new(std::env!("CARGO")) + .arg("run") + .arg("--") + .arg((level - 1).to_string()) + .status() + .unwrap(); + }} + "#, + dylib_path_envvar(), + ), + ) + .build(); + + setenv_for_removing_empty_component(p.cargo("run -- 3")) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 3` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 2` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 1` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE] 0` + +"#]]) + .run(); +} + +// Regression test for #4277 +#[cargo_test] +fn build_with_fake_libc_not_loading() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .file("libc.so.6", r#""#) + .build(); + + setenv_for_removing_empty_component(p.cargo("build")).run(); +} + +// this is testing that src/.rs still works (for now) +#[cargo_test] +fn many_crate_types_old_style_lib_location() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + + name = "foo" + crate-type = ["rlib", "dylib"] + "#, + ) + .file("src/foo.rs", "pub fn foo() {}") + .build(); + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] path `src/foo.rs` was erroneously implicitly accepted for library `foo`, +please rename the file to `src/lib.rs` or set lib.path in Cargo.toml +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(p.root().join("target/debug/libfoo.rlib").is_file()); + let fname = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX); + assert!(p.root().join("target/debug").join(&fname).is_file()); +} + +#[cargo_test] +fn many_crate_types_correct() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + + name = "foo" + crate-type = ["rlib", "dylib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("build").run(); + + assert!(p.root().join("target/debug/libfoo.rlib").is_file()); + let fname = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX); + assert!(p.root().join("target/debug").join(&fname).is_file()); +} + +#[cargo_test] +fn set_both_dylib_and_cdylib_crate_types() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + + name = "foo" + crate-type = ["cdylib", "dylib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + library `foo` cannot set the crate type of both `dylib` and `cdylib` + +"#]]) + .run(); +} + +#[cargo_test] +fn self_dependency() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "test" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.test] + + path = "." + + [lib] + name = "test" + path = "src/test.rs" + "#, + ) + .file("src/test.rs", "fn main() {}") + .build(); + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cyclic package dependency: package `test v0.0.0 ([ROOT]/foo)` depends on itself. Cycle: +package `test v0.0.0 ([ROOT]/foo)` + ... which satisfies path dependency `test` of package `test v0.0.0 ([ROOT]/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +/// Make sure broken and loop symlinks don't break the build +/// +/// This test requires you to be able to make symlinks. +/// For windows, this may require you to enable developer mode. +fn ignore_broken_symlinks() { + if !symlink_supported() { + return; + } + + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", &main_file(r#""i am foo""#, &[])) + .symlink("Notafile", "bar") + // To hit the symlink directory, we need a build script + // to trigger a full scan of package files. + .file("build.rs", &main_file(r#""build script""#, &[])) + .symlink_dir("a/b", "a/b/c/d/foo") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] File system loop found: [ROOT]/foo/a/b/c/d/foo points to an ancestor [ROOT]/foo/a/b +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +i am foo + +"#]]) + .run(); +} + +#[cargo_test] +fn missing_lib_and_bin() { + let p = project().build(); + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + no targets specified in the manifest + either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present + +"#]]) + .run(); +} + +#[cargo_test] +fn lto_build() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "test" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.release] + lto = true + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("build -v --release") + .with_stderr_data(str![[r#" +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn explicit_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + authors = [] + + [lib] + name = "foo" + path = "src/lib.rs" + + [[example]] + name = "hello" + path = "examples/ex-hello.rs" + + [[example]] + name = "goodbye" + path = "examples/ex-goodbye.rs" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn get_hello() -> &'static str { "Hello" } + pub fn get_goodbye() -> &'static str { "Goodbye" } + pub fn get_world() -> &'static str { "World" } + "#, + ) + .file( + "examples/ex-hello.rs", + r#" + extern crate foo; + fn main() { println!("{}, {}!", foo::get_hello(), foo::get_world()); } + "#, + ) + .file( + "examples/ex-goodbye.rs", + r#" + extern crate foo; + fn main() { println!("{}, {}!", foo::get_goodbye(), foo::get_world()); } + "#, + ) + .build(); + + p.cargo("build --examples").run(); + p.process(&p.bin("examples/hello")) + .with_stdout_data(str![[r#" +Hello, World! + +"#]]) + .run(); + p.process(&p.bin("examples/goodbye")) + .with_stdout_data(str![[r#" +Goodbye, World! + +"#]]) + .run(); +} + +#[cargo_test] +fn non_existing_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [lib] + name = "foo" + path = "src/lib.rs" + + [[test]] + name = "hello" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --tests -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `hello` test at `tests/hello.rs` or `tests/hello/main.rs`. Please specify test.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn non_existing_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [lib] + name = "foo" + path = "src/lib.rs" + + [[example]] + name = "hello" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --examples -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `hello` example at `examples/hello.rs` or `examples/hello/main.rs`. Please specify example.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn non_existing_benchmark() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [lib] + name = "foo" + path = "src/lib.rs" + + [[bench]] + name = "hello" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --benches -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `hello` bench at `benches/hello.rs` or `benches/hello/main.rs`. Please specify bench.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn non_existing_binary() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/lib.rs", "") + .file("src/bin/ehlo.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `foo` bin at `src/bin/foo.rs` or `src/bin/foo/main.rs`. Please specify bin.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn commonly_wrong_path_of_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [lib] + name = "foo" + path = "src/lib.rs" + + [[test]] + name = "foo" + "#, + ) + .file("src/lib.rs", "") + .file("test/foo.rs", "") + .build(); + + p.cargo("build --tests -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `foo` test at default paths, but found a file at `test/foo.rs`. + Perhaps rename the file to `tests/foo.rs` for target auto-discovery, or specify test.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn commonly_wrong_path_of_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [lib] + name = "foo" + path = "src/lib.rs" + + [[example]] + name = "foo" + "#, + ) + .file("src/lib.rs", "") + .file("example/foo.rs", "") + .build(); + + p.cargo("build --examples -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `foo` example at default paths, but found a file at `example/foo.rs`. + Perhaps rename the file to `examples/foo.rs` for target auto-discovery, or specify example.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn commonly_wrong_path_of_benchmark() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [lib] + name = "foo" + path = "src/lib.rs" + + [[bench]] + name = "foo" + "#, + ) + .file("src/lib.rs", "") + .file("bench/foo.rs", "") + .build(); + + p.cargo("build --benches -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `foo` bench at default paths, but found a file at `bench/foo.rs`. + Perhaps rename the file to `benches/foo.rs` for target auto-discovery, or specify bench.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn commonly_wrong_path_binary() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/lib.rs", "") + .file("src/bins/foo.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `foo` bin at default paths, but found a file at `src/bins/foo.rs`. + Perhaps rename the file to `src/bin/foo.rs` for target auto-discovery, or specify bin.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn commonly_wrong_path_subdir_binary() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/lib.rs", "") + .file("src/bins/foo/main.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `foo` bin at default paths, but found a file at `src/bins/foo/main.rs`. + Perhaps rename the file to `src/bin/foo/main.rs` for target auto-discovery, or specify bin.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn found_multiple_target_files() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/lib.rs", "") + .file("src/bin/foo.rs", "") + .file("src/bin/foo/main.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + // Don't assert the inferred paths since the order is non-deterministic. + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + cannot infer path for `foo` bin + Cargo doesn't know which to use because multiple target files found at `src/bin/foo[..]rs` and `src/bin/foo[..].rs`. + +"#]]) + .run(); +} + +#[cargo_test] +fn legacy_binary_paths_warnings() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + authors = [] + + [[bin]] + name = "bar" + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[WARNING] An explicit [[bin]] section is specified in Cargo.toml which currently +disables Cargo from automatically inferring other binary targets. +This inference behavior will change in the Rust 2018 edition and the following +files will be included as a binary target: + +* src/main.rs + +This is likely to break cargo build or cargo test as these files may not be +ready to be compiled as a binary target today. You can future-proof yourself +and disable this warning by adding `autobins = false` to your [package] +section. You may also move the files to a location where Cargo would not +automatically infer them to be a target, such as in subfolders. + +For more information on this warning you can consult +https://github.com/rust-lang/cargo/issues/5330 +[WARNING] path `src/main.rs` was erroneously implicitly accepted for binary `bar`, +please set bin.path in Cargo.toml +[COMPILING] foo v1.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + authors = [] + + [[bin]] + name = "bar" + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[WARNING] An explicit [[bin]] section is specified in Cargo.toml which currently +disables Cargo from automatically inferring other binary targets. +This inference behavior will change in the Rust 2018 edition and the following +files will be included as a binary target: + +* src/bin/main.rs + +This is likely to break cargo build or cargo test as these files may not be +ready to be compiled as a binary target today. You can future-proof yourself +and disable this warning by adding `autobins = false` to your [package] +section. You may also move the files to a location where Cargo would not +automatically infer them to be a target, such as in subfolders. + +For more information on this warning you can consult +https://github.com/rust-lang/cargo/issues/5330 +[WARNING] path `src/bin/main.rs` was erroneously implicitly accepted for binary `bar`, +please set bin.path in Cargo.toml +[COMPILING] foo v1.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + authors = [] + + [[bin]] + name = "bar" + "#, + ) + .file("src/bar.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[WARNING] path `src/bar.rs` was erroneously implicitly accepted for binary `bar`, +please set bin.path in Cargo.toml +[COMPILING] foo v1.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn implicit_examples() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn get_hello() -> &'static str { "Hello" } + pub fn get_goodbye() -> &'static str { "Goodbye" } + pub fn get_world() -> &'static str { "World" } + "#, + ) + .file( + "examples/hello.rs", + r#" + extern crate foo; + fn main() { + println!("{}, {}!", foo::get_hello(), foo::get_world()); + } + "#, + ) + .file( + "examples/goodbye.rs", + r#" + extern crate foo; + fn main() { + println!("{}, {}!", foo::get_goodbye(), foo::get_world()); + } + "#, + ) + .build(); + + p.cargo("build --examples").run(); + p.process(&p.bin("examples/hello")) + .with_stdout_data(str![[r#" +Hello, World! + +"#]]) + .run(); + p.process(&p.bin("examples/goodbye")) + .with_stdout_data(str![[r#" +Goodbye, World! + +"#]]) + .run(); +} + +#[cargo_test] +fn standard_build_no_ndebug() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/foo.rs", + r#" + fn main() { + if cfg!(debug_assertions) { + println!("slow") + } else { + println!("fast") + } + } + "#, + ) + .build(); + + p.cargo("build").run(); + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +slow + +"#]]) + .run(); +} + +#[cargo_test] +fn release_build_ndebug() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/foo.rs", + r#" + fn main() { + if cfg!(debug_assertions) { + println!("slow") + } else { + println!("fast") + } + } + "#, + ) + .build(); + + p.cargo("build --release").run(); + p.process(&p.release_bin("foo")) + .with_stdout_data(str![[r#" +fast + +"#]]) + .run(); +} + +#[cargo_test] +fn inferred_main_bin() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("build").run(); + p.process(&p.bin("foo")).run(); +} + +#[cargo_test] +fn deletion_causes_failure() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.change_file("Cargo.toml", &basic_manifest("foo", "0.0.1")); + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +error[E0463]: can't find crate for `bar` +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_cargo_toml_in_target_dir() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("target/Cargo.toml", "bad-toml") + .build(); + + p.cargo("build").run(); + p.process(&p.bin("foo")).run(); +} + +#[cargo_test] +fn lib_with_standard_name() { + let p = project() + .file("Cargo.toml", &basic_manifest("syntax", "0.0.1")) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + "extern crate syntax; fn main() { syntax::foo() }", + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] syntax v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_staticlib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [lib] + name = "foo" + crate-type = ["staticlib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + // env var is a test for #1381 + p.cargo("build").env("CARGO_LOG", "nekoneko=trace").run(); +} + +#[cargo_test] +fn staticlib_rlib_and_bin() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [lib] + name = "foo" + crate-type = ["staticlib", "rlib"] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file("src/main.rs", "extern crate foo; fn main() { foo::foo(); }") + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn opt_out_of_bin() { + let p = project() + .file( + "Cargo.toml", + r#" + bin = [] + + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "bad syntax") + .build(); + p.cargo("build").run(); +} + +#[cargo_test] +fn single_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [lib] + name = "foo" + path = "src/bar.rs" + "#, + ) + .file("src/bar.rs", "") + .build(); + p.cargo("build").run(); +} + +#[cargo_test] +fn freshness_ignores_excluded() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + exclude = ["src/b*.rs"] + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + .build(); + foo.root().move_into_the_past(); + + foo.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Smoke test to make sure it doesn't compile again + println!("first pass"); + foo.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Modify an ignored file and make sure we don't rebuild + println!("second pass"); + foo.change_file("src/bar.rs", ""); + foo.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rebuild_preserves_out_dir() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = 'build.rs' + "#, + ) + .file( + "build.rs", + r#" + use std::env; + use std::fs::File; + use std::path::Path; + + fn main() { + let path = Path::new(&env::var("OUT_DIR").unwrap()).join("foo"); + if env::var_os("FIRST").is_some() { + File::create(&path).unwrap(); + } else { + File::create(&path).unwrap(); + } + } + "#, + ) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + .build(); + foo.root().move_into_the_past(); + + foo.cargo("build") + .env("FIRST", "1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + foo.change_file("src/bar.rs", ""); + foo.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn dep_no_libs() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.0")) + .file("bar/src/main.rs", "") + .build(); + foo.cargo("build").run(); +} + +#[cargo_test] +fn recompile_space_in_name() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [lib] + name = "foo" + path = "src/my lib.rs" + "#, + ) + .file("src/my lib.rs", "") + .build(); + foo.cargo("build").run(); + foo.root().move_into_the_past(); + foo.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cfg(unix)] +#[cargo_test] +fn credentials_is_unreadable() { + use cargo_test_support::paths::home; + use std::os::unix::prelude::*; + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + let credentials = home().join(".cargo/credentials.toml"); + t!(fs::create_dir_all(credentials.parent().unwrap())); + t!(fs::write( + &credentials, + r#" + [registry] + token = "api-token" + "# + )); + let stat = fs::metadata(credentials.as_path()).unwrap(); + let mut perms = stat.permissions(); + perms.set_mode(0o000); + fs::set_permissions(credentials, perms).unwrap(); + + p.cargo("build").run(); +} + +#[cfg(unix)] +#[cargo_test] +fn ignore_bad_directories() { + use std::os::unix::prelude::*; + let foo = project() + .file("Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file("src/lib.rs", "") + .build(); + let dir = foo.root().join("tmp"); + fs::create_dir(&dir).unwrap(); + let stat = fs::metadata(&dir).unwrap(); + let mut perms = stat.permissions(); + perms.set_mode(0o644); + fs::set_permissions(&dir, perms.clone()).unwrap(); + foo.cargo("build").run(); + perms.set_mode(0o755); + fs::set_permissions(&dir, perms).unwrap(); +} + +#[cargo_test] +fn bad_cargo_config() { + let foo = project() + .file("Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file("src/lib.rs", "") + .file(".cargo/config.toml", "this is not valid toml") + .build(); + foo.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not load Cargo configuration + +Caused by: + could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml` + +Caused by: + TOML parse error at line 1, column 6 + | + 1 | this is not valid toml + | ^ + expected `.`, `=` + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_platform_specific_dependency() { + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + + [target.{host}.dependencies] + dep = {{ path = "dep" }} + [target.{host}.build-dependencies] + build = {{ path = "build" }} + [target.{host}.dev-dependencies] + dev = {{ path = "dev" }} + "#, + host = host + ), + ) + .file("src/main.rs", "extern crate dep; fn main() { dep::dep() }") + .file( + "tests/foo.rs", + "extern crate dev; #[test] fn foo() { dev::dev() }", + ) + .file( + "build.rs", + "extern crate build; fn main() { build::build(); }", + ) + .file("dep/Cargo.toml", &basic_manifest("dep", "0.5.0")) + .file("dep/src/lib.rs", "pub fn dep() {}") + .file("build/Cargo.toml", &basic_manifest("build", "0.5.0")) + .file("build/src/lib.rs", "pub fn build() {}") + .file("dev/Cargo.toml", &basic_manifest("dev", "0.5.0")) + .file("dev/src/lib.rs", "pub fn dev() {}") + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + p.cargo("test").run(); +} + +#[cargo_test] +fn bad_platform_specific_dependency() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [target.wrong-target.dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file( + "bar/src/lib.rs", + r#"pub fn gimme() -> String { format!("") }"#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.5.0 ([ROOT]/foo) +error[E0463]: can't find crate for `bar` +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_platform_specific_dependency_wrong_platform() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [target.non-existing-triplet.dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file( + "bar/src/lib.rs", + "invalid rust file, should not be compiled", + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + p.process(&p.bin("foo")).run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("bar")); +} + +#[cargo_test] +fn example_as_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex" + crate-type = ["lib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("build --example=ex").run(); + assert!(p.example_lib("ex", "lib").is_file()); +} + +#[cargo_test] +fn example_as_rlib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex" + crate-type = ["rlib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("build --example=ex").run(); + assert!(p.example_lib("ex", "rlib").is_file()); +} + +#[cargo_test] +fn example_as_dylib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex" + crate-type = ["dylib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("build --example=ex").run(); + assert!(p.example_lib("ex", "dylib").is_file()); +} + +#[cargo_test] +fn example_as_proc_macro() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex" + crate-type = ["proc-macro"] + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro] + pub fn eat(_item: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .build(); + + p.cargo("build --example=ex").run(); + assert!(p.example_lib("ex", "proc-macro").is_file()); +} + +#[cargo_test] +fn example_bin_same_name() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("examples/foo.rs", "fn main() {}") + .build(); + + p.cargo("build --examples").run(); + + assert!(!p.bin("foo").is_file()); + // We expect a file of the form bin/foo-{metadata_hash} + assert!(p.bin("examples/foo").is_file()); + + p.cargo("build --examples").run(); + + assert!(!p.bin("foo").is_file()); + // We expect a file of the form bin/foo-{metadata_hash} + assert!(p.bin("examples/foo").is_file()); +} + +#[cargo_test] +fn compile_then_delete() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("run -v").run(); + assert!(p.bin("foo").is_file()); + if cfg!(windows) { + // On windows unlinking immediately after running often fails, so sleep + sleep_ms(100); + } + fs::remove_file(&p.bin("foo")).unwrap(); + p.cargo("run -v").run(); +} + +#[cargo_test] +fn transitive_dependencies_not_available() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.aaaaa] + path = "a" + "#, + ) + .file( + "src/main.rs", + "extern crate bbbbb; extern crate aaaaa; fn main() {}", + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "aaaaa" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bbbbb] + path = "../b" + "#, + ) + .file("a/src/lib.rs", "extern crate bbbbb;") + .file("b/Cargo.toml", &basic_manifest("bbbbb", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bbbbb v0.0.1 ([ROOT]/foo/b) +[RUNNING] `rustc [..] +[COMPILING] aaaaa v0.0.1 ([ROOT]/foo/a) +[RUNNING] `rustc [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +error[E0463]: can't find crate for `bbbbb` +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +Caused by: + process didn't exit successfully: `rustc [..]` ([EXIT_STATUS]: 1) + +"#]]) + .run(); +} + +#[cargo_test] +fn cyclic_deps_rejected() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.foo] + path = ".." + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cyclic package dependency: package `a v0.0.1 ([ROOT]/foo/a)` depends on itself. Cycle: +package `a v0.0.1 ([ROOT]/foo/a)` + ... which satisfies path dependency `a` of package `foo v0.0.1 ([ROOT]/foo)` + ... which satisfies path dependency `foo` of package `a v0.0.1 ([ROOT]/foo/a)` + +"#]]) + .run(); +} + +#[cargo_test] +fn predictable_filenames() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + crate-type = ["dylib", "rlib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v").run(); + assert!(p.root().join("target/debug/libfoo.rlib").is_file()); + let dylib_name = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX); + assert!(p.root().join("target/debug").join(dylib_name).is_file()); +} + +#[cargo_test] +fn dashes_to_underscores() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo-bar", "0.0.1")) + .file("src/lib.rs", "") + .file("src/main.rs", "extern crate foo_bar; fn main() {}") + .build(); + + p.cargo("build -v").run(); + assert!(p.bin("foo-bar").is_file()); +} + +#[cargo_test] +fn dashes_in_crate_name_bad() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo-bar" + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "extern crate foo_bar; fn main() {}") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + library target names cannot contain hyphens: foo-bar + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_env_var() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("build -v") + .env("RUSTC", "rustc-that-does-not-exist") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not execute process `rustc-that-does-not-exist -vV` (never executed) + +Caused by: + [..] + +"#]]) + .run(); + assert!(!p.bin("a").is_file()); +} + +#[cargo_test] +fn filtering() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("src/bin/b.rs", "fn main() {}") + .file("examples/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .build(); + + p.cargo("build --lib").run(); + assert!(!p.bin("a").is_file()); + + p.cargo("build --bin=a --example=a").run(); + assert!(p.bin("a").is_file()); + assert!(!p.bin("b").is_file()); + assert!(p.bin("examples/a").is_file()); + assert!(!p.bin("examples/b").is_file()); +} + +#[cargo_test] +fn filtering_implicit_bins() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("src/bin/b.rs", "fn main() {}") + .file("examples/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .build(); + + p.cargo("build --bins").run(); + assert!(p.bin("a").is_file()); + assert!(p.bin("b").is_file()); + assert!(!p.bin("examples/a").is_file()); + assert!(!p.bin("examples/b").is_file()); +} + +#[cargo_test] +fn filtering_implicit_examples() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("src/bin/b.rs", "fn main() {}") + .file("examples/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .build(); + + p.cargo("build --examples").run(); + assert!(!p.bin("a").is_file()); + assert!(!p.bin("b").is_file()); + assert!(p.bin("examples/a").is_file()); + assert!(p.bin("examples/b").is_file()); +} + +#[cargo_test] +fn ignore_dotfile() { + let p = project() + .file("src/bin/.a.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); +} + +#[cargo_test] +fn ignore_dotdirs() { + let p = project() + .file("src/bin/a.rs", "fn main() {}") + .file(".git/Cargo.toml", "") + .file(".pc/dummy-fix.patch/Cargo.toml", "") + .build(); + + p.cargo("build").run(); +} + +#[cargo_test] +fn dotdir_root() { + let p = ProjectBuilder::new(root().join(".foo")) + .file("src/bin/a.rs", "fn main() {}") + .build(); + p.cargo("build").run(); +} + +#[cargo_test] +fn custom_target_dir_env() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + let exe_name = format!("foo{}", env::consts::EXE_SUFFIX); + + p.cargo("build").env("CARGO_TARGET_DIR", "foo/target").run(); + assert!(p.root().join("foo/target/debug").join(&exe_name).is_file()); + assert!(!p.root().join("target/debug").join(&exe_name).is_file()); + + p.cargo("build").run(); + assert!(p.root().join("foo/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("target/debug").join(&exe_name).is_file()); + + p.cargo("build") + .env("CARGO_BUILD_TARGET_DIR", "foo2/target") + .run(); + assert!(p.root().join("foo2/target/debug").join(&exe_name).is_file()); + + p.change_file( + ".cargo/config.toml", + r#" + [build] + target-dir = "foo/target" + "#, + ); + p.cargo("build").env("CARGO_TARGET_DIR", "bar/target").run(); + assert!(p.root().join("bar/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("foo/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("target/debug").join(&exe_name).is_file()); +} + +#[cargo_test] +fn custom_target_dir_line_parameter() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + let exe_name = format!("foo{}", env::consts::EXE_SUFFIX); + + p.cargo("build --target-dir foo/target").run(); + assert!(p.root().join("foo/target/debug").join(&exe_name).is_file()); + assert!(!p.root().join("target/debug").join(&exe_name).is_file()); + + p.cargo("build").run(); + assert!(p.root().join("foo/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("target/debug").join(&exe_name).is_file()); + + p.change_file( + ".cargo/config.toml", + r#" + [build] + target-dir = "foo/target" + "#, + ); + p.cargo("build --target-dir bar/target").run(); + assert!(p.root().join("bar/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("foo/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("target/debug").join(&exe_name).is_file()); + + p.cargo("build --target-dir foobar/target") + .env("CARGO_TARGET_DIR", "bar/target") + .run(); + assert!(p + .root() + .join("foobar/target/debug") + .join(&exe_name) + .is_file()); + assert!(p.root().join("bar/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("foo/target/debug").join(&exe_name).is_file()); + assert!(p.root().join("target/debug").join(&exe_name).is_file()); +} + +#[cargo_test] +fn build_multiple_packages() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "d1" + [dependencies.d2] + path = "d2" + + [[bin]] + name = "foo" + "#, + ) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .file("d1/Cargo.toml", &basic_bin_manifest("d1")) + .file("d1/src/lib.rs", "") + .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }") + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "d2" + doctest = false + "#, + ) + .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }") + .build(); + + p.cargo("build -p d1 -p d2 -p foo").run(); + + assert!(p.bin("foo").is_file()); + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +i am foo + +"#]]) + .run(); + + let d1_path = &p + .build_dir() + .join("debug") + .join(format!("d1{}", env::consts::EXE_SUFFIX)); + let d2_path = &p + .build_dir() + .join("debug") + .join(format!("d2{}", env::consts::EXE_SUFFIX)); + + assert!(d1_path.is_file()); + p.process(d1_path) + .with_stdout_data(str![[r#" +d1 + +"#]]) + .run(); + + assert!(d2_path.is_file()); + p.process(d2_path) + .with_stdout_data(str![[r#" +d2 + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_spec() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "d1" + + [[bin]] + name = "foo" + "#, + ) + .file("src/bin/foo.rs", &main_file(r#""i am foo""#, &[])) + .file("d1/Cargo.toml", &basic_bin_manifest("d1")) + .file("d1/src/lib.rs", "") + .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }") + .build(); + + p.cargo("build -p notAValidDep") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] package ID specification `notAValidDep` did not match any packages + +"#]]) + .run(); + + p.cargo("build -p d1 -p notAValidDep") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `notAValidDep` did not match any packages + +"#]]) + .run(); +} + +#[cargo_test] +fn manifest_with_bom_is_ok() { + let p = project() + .file( + "Cargo.toml", + "\u{FEFF} + [package] + name = \"foo\" + version = \"0.0.1\" + edition = \"2015\" + authors = [] + ", + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build -v").run(); +} + +#[cargo_test] +fn panic_abort_compiles_with_panic_abort() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.dev] + panic = 'abort' + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] -C panic=abort [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn compiler_json_error_format() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + "build.rs", + "fn main() { println!(\"cargo::rustc-cfg=xyz\") }", + ) + .file("src/main.rs", "fn main() { let unused = 92; }") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("bar/src/lib.rs", r#"fn dead() {}"#) + .build(); + + let output = |fresh| { + r#" +[ + { + "executable": null, + "features": [], + "fresh": $FRESH, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-artifact", + "target": { + "kind": ["custom-build"], + "...": "{...}" + }, + "...": "{...}" + }, + { + "manifest_path": "[ROOT]/foo/bar/Cargo.toml", + "package_id": "path+[ROOTURL]/foo/bar#0.5.0", + "reason": "compiler-message", + "target": { + "kind": ["lib"], + "...": "{...}" + }, + "...": "{...}" + }, + { + "executable": null, + "features": [], + "fresh": $FRESH, + "manifest_path": "[ROOT]/foo/bar/Cargo.toml", + "package_id": "path+[ROOTURL]/foo/bar#0.5.0", + "reason": "compiler-artifact", + "target": { + "kind": ["lib"], + "...": "{...}" + }, + "...": "{...}" + }, + { + "cfgs": [ + "xyz" + ], + "env": [], + "linked_libs": [], + "linked_paths": [], + "out_dir": "[ROOT]/foo/target/debug/build/foo-[HASH]/out", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "build-script-executed" + }, + { + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-message", + "target": { + "kind": ["bin"], + "...": "{...}" + }, + "...": "{...}" + }, + { + "features": [], + "fresh": $FRESH, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-artifact", + "target": { + "kind": ["bin"], + "...": "{...}" + }, + "...": "{...}" + }, + { + "reason": "build-finished", + "success": true + }, + "{...}" +] +"# + .replace("$FRESH", fresh) + .is_json() + .against_jsonlines() + .unordered() + }; + + // Use `jobs=1` to ensure that the order of messages is consistent. + p.cargo("build -v --message-format=json --jobs=1") + .with_stdout_data(output("false")) + .run(); + + // With fresh build, we should repeat the artifacts, + // and replay the cached compiler warnings. + p.cargo("build -v --message-format=json --jobs=1") + .with_stdout_data(output("true")) + .run(); +} + +#[cargo_test] +fn wrong_message_format_option() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --message-format XML") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid message format specifier: `xml` + +"#]]) + .run(); +} + +#[cargo_test] +fn message_format_json_forward_stderr() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() { let unused = 0; }") + .build(); + + p.cargo("rustc --release --bin foo --message-format JSON") + .with_stdout_data( + str![[r#" +[ + { + "manifest_path": "[ROOT]/foo/Cargo.toml", + "message": "{...}", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-message", + "target": { + "kind": ["bin"], + "...": "{...}" + }, + "...": "{...}" + }, + { + "features": [], + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-artifact", + "target": { + "kind": ["bin"], + "...": "{...}" + }, + "...": "{...}" + }, + { + "reason": "build-finished", + "success": true + }, + "{...}" +] +"#]] + .is_json() + .against_jsonlines() + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn no_warn_about_package_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [package.metadata] + foo = "bar" + a = true + b = 3 + + [package.metadata.another] + bar = 3 + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn no_warn_about_workspace_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + + [workspace.metadata] + something = "something_else" + x = 1 + y = 2 + + [workspace.metadata.another] + bar = 12 + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_build_empty_target() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --target") + .arg("") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target was empty + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_build_with_unsupported_short_target_flag() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -t") + .arg("") + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '-t' found + + tip: a similar argument exists: '--target' + +Usage: cargo[EXE] build [OPTIONS] + +For more information, try '--help'. + +"#]]) + .with_status(1) + .run(); +} + +#[cargo_test] +fn build_all_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build --workspace") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_all_exclude() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("build --workspace --exclude baz") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn cargo_build_with_unsupported_short_exclude_flag() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("build --workspace -x baz") + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '-x' found + + tip: a similar argument exists: '--exclude' + +Usage: cargo[EXE] build [OPTIONS] + +For more information, try '--help'. + +"#]]) + .with_status(1) + .run(); +} + +#[cargo_test] +fn build_all_exclude_not_found() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build --workspace --exclude baz") + .with_stderr_data( + str![[r#" +[WARNING] excluded package(s) `baz` not found in workspace `[ROOT]/foo` +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_all_exclude_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("build --workspace --exclude '*z'") + .with_stderr_data( + str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_all_exclude_glob_not_found() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build --workspace --exclude '*z'") + .with_stderr_data( + str![[r#" +[WARNING] excluded package pattern(s) `*z` not found in workspace `[ROOT]/foo` +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_all_exclude_broken_glob() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("build --workspace --exclude '[*z'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot build glob pattern from `[*z` + +Caused by: +... + +"#]]) + .run(); +} + +#[cargo_test] +fn build_all_workspace_implicit_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("src/bin/b.rs", "fn main() {}") + .file("examples/c.rs", "fn main() {}") + .file("examples/d.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .file("bar/src/bin/e.rs", "fn main() {}") + .file("bar/src/bin/f.rs", "fn main() {}") + .file("bar/examples/g.rs", "fn main() {}") + .file("bar/examples/h.rs", "fn main() {}") + .build(); + + p.cargo("build --workspace --examples") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(!p.bin("a").is_file()); + assert!(!p.bin("b").is_file()); + assert!(p.bin("examples/c").is_file()); + assert!(p.bin("examples/d").is_file()); + assert!(!p.bin("e").is_file()); + assert!(!p.bin("f").is_file()); + assert!(p.bin("examples/g").is_file()); + assert!(p.bin("examples/h").is_file()); +} + +#[cargo_test] +fn build_all_virtual_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + // The order in which bar and baz are built is not guaranteed + p.cargo("build --workspace") + .with_stderr_data( + str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_virtual_manifest_all_implied() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + // The order in which `bar` and `baz` are built is not guaranteed. + p.cargo("build") + .with_stderr_data( + str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_virtual_manifest_one_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("build -p bar") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_virtual_manifest_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() { break_the_build(); }") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("build -p '*z'") + .with_stderr_data(str![[r#" +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_virtual_manifest_glob_not_found() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build -p bar -p '*z'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package pattern(s) `*z` not found in workspace `[ROOT]/foo` + +"#]]) + .run(); +} + +#[cargo_test] +fn build_virtual_manifest_broken_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build -p '[*z'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot build glob pattern from `[*z` + +Caused by: +... + +"#]]) + .run(); +} + +#[cargo_test] +fn build_all_virtual_manifest_implicit_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .file("bar/src/bin/a.rs", "fn main() {}") + .file("bar/src/bin/b.rs", "fn main() {}") + .file("bar/examples/c.rs", "fn main() {}") + .file("bar/examples/d.rs", "fn main() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "") + .file("baz/src/bin/e.rs", "fn main() {}") + .file("baz/src/bin/f.rs", "fn main() {}") + .file("baz/examples/g.rs", "fn main() {}") + .file("baz/examples/h.rs", "fn main() {}") + .build(); + + // The order in which bar and baz are built is not guaranteed + p.cargo("build --workspace --examples") + .with_stderr_data( + str![[r#" +[COMPILING] baz v0.1.0 ([ROOT]/foo/baz) +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + assert!(!p.bin("a").is_file()); + assert!(!p.bin("b").is_file()); + assert!(p.bin("examples/c").is_file()); + assert!(p.bin("examples/d").is_file()); + assert!(!p.bin("e").is_file()); + assert!(!p.bin("f").is_file()); + assert!(p.bin("examples/g").is_file()); + assert!(p.bin("examples/h").is_file()); +} + +#[cargo_test] +fn build_all_member_dependency_same_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dependencies] + a = "0.1.0" + "#, + ) + .file("a/src/lib.rs", "pub fn a() {}") + .build(); + + Package::new("a", "0.1.0").publish(); + + p.cargo("build --workspace") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.1.0 (registry `dummy-registry`) +[COMPILING] a v0.1.0 +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn run_proper_binary() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + [[bin]] + name = "main" + [[bin]] + name = "other" + "#, + ) + .file("src/lib.rs", "") + .file( + "src/bin/main.rs", + r#"fn main() { panic!("This should never be run."); }"#, + ) + .file("src/bin/other.rs", "fn main() {}") + .build(); + + p.cargo("run --bin other").run(); +} + +#[cargo_test] +fn run_proper_binary_main_rs() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/lib.rs", "") + .file("src/bin/main.rs", "fn main() {}") + .build(); + + p.cargo("run --bin foo").run(); +} + +#[cargo_test] +fn run_proper_alias_binary_from_src() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + [[bin]] + name = "foo" + [[bin]] + name = "bar" + "#, + ) + .file("src/foo.rs", r#"fn main() { println!("foo"); }"#) + .file("src/bar.rs", r#"fn main() { println!("bar"); }"#) + .build(); + + p.cargo("build --workspace").run(); + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); + p.process(&p.bin("bar")) + .with_stdout_data(str![[r#" +bar + +"#]]) + .run(); +} + +#[cargo_test] +fn run_proper_alias_binary_main_rs() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + [[bin]] + name = "foo" + [[bin]] + name = "bar" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("main"); }"#) + .build(); + + p.cargo("build --workspace").run(); + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +main + +"#]]) + .run(); + p.process(&p.bin("bar")) + .with_stdout_data(str![[r#" +main + +"#]]) + .run(); +} + +#[cargo_test] +fn run_proper_binary_main_rs_as_foo() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/foo.rs", + r#" fn main() { panic!("This should never be run."); }"#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("run --bin foo").run(); +} + +#[cargo_test] +fn rustc_wrapper() { + let p = project().file("src/lib.rs", "").build(); + let wrapper = tools::echo_wrapper(); + p.cargo("build -v") + .env("RUSTC_WRAPPER", &wrapper) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..]/rustc-echo-wrapper[EXE] rustc --crate-name foo [..]` +WRAPPER CALLED: rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.build_dir().rm_rf(); + p.cargo("build -v") + .env("RUSTC_WORKSPACE_WRAPPER", &wrapper) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..]/rustc-echo-wrapper[EXE] rustc --crate-name foo [..]` +WRAPPER CALLED: rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +/// Checks what happens when both rust-wrapper and rustc-workspace-wrapper are set. +#[cargo_test] +fn rustc_wrapper_precendence() { + let p = project().file("src/lib.rs", "").build(); + let rustc_wrapper = tools::echo_wrapper(); + let ws_wrapper = rustc_wrapper.with_file_name("rustc-ws-wrapper"); + assert_ne!(rustc_wrapper, ws_wrapper); + std::fs::hard_link(&rustc_wrapper, &ws_wrapper).unwrap(); + + p.cargo("build -v") + .env("RUSTC_WRAPPER", &rustc_wrapper) + .env("RUSTC_WORKSPACE_WRAPPER", &ws_wrapper) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..]/rustc-echo-wrapper[EXE] [..]/rustc-ws-wrapper rustc --crate-name foo [..]` +WRAPPER CALLED: [..]/rustc-ws-wrapper rustc --crate-name foo [..] +WRAPPER CALLED: rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_wrapper_queries() { + // Check that the invocations querying rustc for information are done with the wrapper. + let p = project().file("src/lib.rs", "").build(); + let wrapper = tools::echo_wrapper(); + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env("RUSTC_WRAPPER", &wrapper) + .with_stderr_contains("[..]running [..]rustc-echo-wrapper[EXE] rustc -vV[..]") + .with_stderr_contains( + "[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ --print[..]", + ) + .run(); + p.build_dir().rm_rf(); + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env("RUSTC_WORKSPACE_WRAPPER", &wrapper) + .with_stderr_contains("[..]running [..]rustc-echo-wrapper[EXE] rustc -vV[..]") + .with_stderr_contains( + "[..]running [..]rustc-echo-wrapper[EXE] rustc - --crate-name ___ --print[..]", + ) + .run(); +} + +#[cargo_test] +fn rustc_wrapper_relative() { + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + let wrapper = tools::echo_wrapper(); + let exe_name = wrapper.file_name().unwrap().to_str().unwrap(); + let relative_path = format!("./{}", exe_name); + fs::hard_link(&wrapper, p.root().join(exe_name)).unwrap(); + p.cargo("build -v") + .env("RUSTC_WRAPPER", &relative_path) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[COMPILING] bar v1.0.0 +[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name bar [..]` +WRAPPER CALLED: rustc --crate-name bar [..] +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name foo [..]` +WRAPPER CALLED: rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.build_dir().rm_rf(); + p.cargo("build -v") + .env("RUSTC_WORKSPACE_WRAPPER", &relative_path) + .with_stderr_data(str![[r#" +[COMPILING] bar v1.0.0 +[RUNNING] `rustc --crate-name bar [..]` +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name foo [..]` +WRAPPER CALLED: rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.build_dir().rm_rf(); + p.change_file( + ".cargo/config.toml", + &format!( + r#" + build.rustc-wrapper = "./{}" + "#, + exe_name + ), + ); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] bar v1.0.0 +[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name bar [..]` +WRAPPER CALLED: rustc --crate-name bar [..] +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/./rustc-echo-wrapper[EXE] rustc --crate-name foo [..]` +WRAPPER CALLED: rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_wrapper_from_path() { + let p = project().file("src/lib.rs", "").build(); + p.cargo("build -v") + .env("RUSTC_WRAPPER", "wannabe_sccache") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not execute process `wannabe_sccache rustc -vV` (never executed) + +Caused by: + [..] + +"#]]) + .run(); + p.build_dir().rm_rf(); + p.cargo("build -v") + .env("RUSTC_WORKSPACE_WRAPPER", "wannabe_sccache") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not execute process `wannabe_sccache rustc -vV` (never executed) + +Caused by: + [..] + +"#]]) + .run(); +} + +#[cargo_test] +fn cdylib_not_lifted() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["cdylib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + let files = if cfg!(windows) { + if cfg!(target_env = "msvc") { + vec!["foo.dll.lib", "foo.dll.exp", "foo.dll"] + } else { + vec!["libfoo.dll.a", "foo.dll"] + } + } else if cfg!(target_os = "macos") { + vec!["libfoo.dylib"] + } else { + vec!["libfoo.so"] + }; + + for file in files { + println!("checking: {}", file); + assert!(p.root().join("target/debug/deps").join(&file).is_file()); + } +} + +#[cargo_test] +fn cdylib_final_outputs() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo-bar" + authors = [] + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["cdylib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + let files = if cfg!(windows) { + if cfg!(target_env = "msvc") { + vec!["foo_bar.dll.lib", "foo_bar.dll"] + } else { + vec!["foo_bar.dll", "libfoo_bar.dll.a"] + } + } else if cfg!(target_os = "macos") { + vec!["libfoo_bar.dylib"] + } else { + vec!["libfoo_bar.so"] + }; + + for file in files { + println!("checking: {}", file); + assert!(p.root().join("target/debug").join(&file).is_file()); + } +} + +#[cargo_test] +// NOTE: Windows MSVC and wasm32-unknown-emscripten do not use metadata. Skip them. +// See +#[cfg(not(all(target_os = "windows", target_env = "msvc")))] +fn no_dep_info_collision_when_cdylib_and_bin_coexist() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + + [lib] + crate-type = ["cdylib"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data( + str![[r#" +[COMPILING] foo v1.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..] --crate-type bin [..] -C metadata=[..]` +[RUNNING] `rustc [..] --crate-type cdylib [..] -C metadata=[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + let deps_dir = p.target_debug_dir().join("deps"); + assert!(deps_dir.join("foo.d").exists()); + let dep_info_count = deps_dir + .read_dir() + .unwrap() + .filter(|e| { + let filename = e.as_ref().unwrap().file_name(); + let filename = filename.to_str().unwrap(); + filename.starts_with("foo") && filename.ends_with(".d") + }) + .count(); + // cdylib -> foo.d + // bin -> foo-.d + assert_eq!(dep_info_count, 2); +} + +#[cargo_test] +fn deterministic_cfg_flags() { + // This bug is non-deterministic. + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + + [features] + default = ["f_a", "f_b", "f_c", "f_d"] + f_a = [] + f_b = [] + f_c = [] + f_d = [] + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-cfg=cfg_a"); + println!("cargo::rustc-cfg=cfg_b"); + println!("cargo::rustc-cfg=cfg_c"); + println!("cargo::rustc-cfg=cfg_d"); + println!("cargo::rustc-cfg=cfg_e"); + } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] --cfg[..]default[..]--cfg[..]f_a[..]--cfg[..]f_b[..] --cfg[..]f_c[..]--cfg[..]f_d[..] --cfg cfg_a --cfg cfg_b --cfg cfg_c --cfg cfg_d --cfg cfg_e` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn explicit_bins_without_paths() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [[bin]] + name = "foo" + + [[bin]] + name = "bar" + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); +} + +#[cargo_test] +fn no_bin_in_src_with_lib() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/lib.rs", "") + .file("src/foo.rs", "fn main() {}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + can't find `foo` bin at `src/bin/foo.rs` or `src/bin/foo/main.rs`. Please specify bin.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +fn inferred_bins() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .file("src/bin/baz/main.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + assert!(p.bin("baz").is_file()); +} + +#[cargo_test] +fn inferred_bins_duplicate_name() { + // this should fail, because we have two binaries with the same name + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .file("src/bin/bar/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + found duplicate binary name bar, but all binary targets must have a unique name + +"#]]) + .run(); +} + +#[cargo_test] +fn inferred_bin_path() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [[bin]] + name = "bar" + # Note, no `path` key! + "#, + ) + .file("src/bin/bar/main.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); + assert!(p.bin("bar").is_file()); +} + +#[cargo_test] +fn inferred_examples() { + let p = project() + .file("src/lib.rs", "fn main() {}") + .file("examples/bar.rs", "fn main() {}") + .file("examples/baz/main.rs", "fn main() {}") + .build(); + + p.cargo("build --examples").run(); + assert!(p.bin("examples/bar").is_file()); + assert!(p.bin("examples/baz").is_file()); +} + +#[cargo_test] +fn inferred_tests() { + let p = project() + .file("src/lib.rs", "fn main() {}") + .file("tests/bar.rs", "fn main() {}") + .file("tests/baz/main.rs", "fn main() {}") + .build(); + + p.cargo("test --test=bar --test=baz").run(); +} + +#[cargo_test] +fn inferred_benchmarks() { + let p = project() + .file("src/lib.rs", "fn main() {}") + .file("benches/bar.rs", "fn main() {}") + .file("benches/baz/main.rs", "fn main() {}") + .build(); + + p.cargo("bench --bench=bar --bench=baz").run(); +} + +#[cargo_test] +fn no_infer_dirs() { + let p = project() + .file("src/lib.rs", "fn main() {}") + .file("examples/dir.rs/dummy", "") + .file("benches/dir.rs/dummy", "") + .file("tests/dir.rs/dummy", "") + .build(); + + p.cargo("build --examples --benches --tests").run(); // should not fail with "is a directory" +} + +#[cargo_test] +fn target_edition() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [lib] + edition = "2018" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]--edition=2018 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn target_edition_override() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2018" + + [lib] + edition = "2015" + "#, + ) + .file( + "src/lib.rs", + " + pub fn async() {} + pub fn try() {} + pub fn await() {} + ", + ) + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn same_metadata_different_directory() { + // A top-level crate built in two different workspaces should have the + // same metadata hash. + let p = project() + .at("foo1") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + let output = t!(String::from_utf8(p.cargo("build -v").run().stderr,)); + let metadata = output + .split_whitespace() + .find(|arg| arg.starts_with("metadata=")) + .unwrap(); + + let p = project() + .at("foo2") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build -v") + .with_stderr_data(format!("...\n[..]{metadata}[..]\n...")) + .run(); +} + +#[cargo_test] +fn building_a_dependent_crate_without_bin_should_fail() { + Package::new("testless", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "testless" + version = "0.1.0" + edition = "2015" + + [[bin]] + name = "a_bin" + "#, + ) + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + testless = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] testless v0.1.0 (registry `dummy-registry`) +[ERROR] failed to download replaced source registry `crates-io` + +Caused by: + failed to parse manifest at `[ROOT]/home/.cargo/registry/src/-[HASH]/testless-0.1.0/Cargo.toml` + +Caused by: + can't find `a_bin` bin at `src/bin/a_bin.rs` or `src/bin/a_bin/main.rs`. Please specify bin.path if you want to use a non-default path. + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(any(target_os = "macos", target_os = "ios"))] +fn uplift_dsym_of_bin_on_mac() { + let p = project() + .file("src/main.rs", "fn main() { panic!(); }") + .file("src/bin/b.rs", "fn main() { panic!(); }") + .file("examples/c.rs", "fn main() { panic!(); }") + .file("tests/d.rs", "fn main() { panic!(); }") + .build(); + + p.cargo("build --bins --examples --tests") + .enable_mac_dsym() + .run(); + assert!(p.target_debug_dir().join("foo.dSYM").is_dir()); + assert!(p.target_debug_dir().join("b.dSYM").is_dir()); + assert!(p.target_debug_dir().join("b.dSYM").is_symlink()); + assert!(p.target_debug_dir().join("examples/c.dSYM").is_dir()); + assert!(!p.target_debug_dir().join("c.dSYM").exists()); + assert!(!p.target_debug_dir().join("d.dSYM").exists()); +} + +#[cargo_test] +#[cfg(any(target_os = "macos", target_os = "ios"))] +fn uplift_dsym_of_bin_on_mac_when_broken_link_exists() { + let p = project() + .file("src/main.rs", "fn main() { panic!(); }") + .build(); + let dsym = p.target_debug_dir().join("foo.dSYM"); + + p.cargo("build").enable_mac_dsym().run(); + assert!(dsym.is_dir()); + + // Simulate the situation where the underlying dSYM bundle goes missing + // but the uplifted symlink to it remains. This would previously cause + // builds to permanently fail until the bad symlink was manually removed. + dsym.rm_rf(); + p.symlink( + p.target_debug_dir() + .join("deps") + .join("foo-baaaaaadbaaaaaad.dSYM"), + &dsym, + ); + assert!(dsym.is_symlink()); + assert!(!dsym.exists()); + + p.cargo("build").enable_mac_dsym().run(); + assert!(dsym.is_dir()); +} + +#[cargo_test] +#[cfg(all(target_os = "windows", target_env = "msvc"))] +fn uplift_pdb_of_bin_on_windows() { + let p = project() + .file("src/main.rs", "fn main() { panic!(); }") + .file("src/bin/b.rs", "fn main() { panic!(); }") + .file("src/bin/foo-bar.rs", "fn main() { panic!(); }") + .file("examples/c.rs", "fn main() { panic!(); }") + .file("tests/d.rs", "fn main() { panic!(); }") + .build(); + + p.cargo("build --bins --examples --tests").run(); + assert!(p.target_debug_dir().join("foo.pdb").is_file()); + assert!(p.target_debug_dir().join("b.pdb").is_file()); + assert!(p.target_debug_dir().join("examples/c.pdb").exists()); + assert!(p.target_debug_dir().join("foo-bar.exe").is_file()); + assert!(p.target_debug_dir().join("foo_bar.pdb").is_file()); + assert!(!p.target_debug_dir().join("c.pdb").exists()); + assert!(!p.target_debug_dir().join("d.pdb").exists()); +} + +#[cargo_test] +#[cfg(target_os = "linux")] +fn uplift_dwp_of_bin_on_linux() { + let p = project() + .file("src/main.rs", "fn main() { panic!(); }") + .file("src/bin/b.rs", "fn main() { panic!(); }") + .file("src/bin/foo-bar.rs", "fn main() { panic!(); }") + .file("examples/c.rs", "fn main() { panic!(); }") + .file("tests/d.rs", "fn main() { panic!(); }") + .build(); + + p.cargo("build --bins --examples --tests") + .enable_split_debuginfo_packed() + .run(); + assert!(p.target_debug_dir().join("foo.dwp").is_file()); + assert!(p.target_debug_dir().join("b.dwp").is_file()); + assert!(p.target_debug_dir().join("examples/c.dwp").exists()); + assert!(p.target_debug_dir().join("foo-bar").is_file()); + assert!(p.target_debug_dir().join("foo-bar.dwp").is_file()); + assert!(!p.target_debug_dir().join("c.dwp").exists()); + assert!(!p.target_debug_dir().join("d.dwp").exists()); +} + +// Ensure that `cargo build` chooses the correct profile for building +// targets based on filters (assuming `--profile` is not specified). +#[cargo_test] +fn build_filter_infer_profile() { + let p = project() + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .file("tests/t1.rs", "") + .file("benches/b1.rs", "") + .file("examples/ex1.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); + + p.root().join("target").rm_rf(); + p.cargo("build -v --test=t1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..] -C debuginfo=2 [..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..] -C debuginfo=2 [..]` +[RUNNING] `rustc --crate-name t1 --edition=2015 tests/t1.rs [..]--emit=[..]link[..] -C debuginfo=2 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); + + p.root().join("target").rm_rf(); + // Bench uses test profile without `--release`. + p.cargo("build -v --bench=b1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link [..]-C debuginfo=2 [..]` +[RUNNING] `rustc --crate-name b1 --edition=2015 benches/b1.rs [..]--emit=[..]link[..] -C embed-bitcode=no -C debuginfo=2 [..]--test [..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link [..]-C debuginfo=2 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn targets_selected_default() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("build -v") + // Binaries. + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin \ + --emit=[..]link[..]", + ) + // Benchmarks. + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link \ + -C opt-level=3 --test [..]", + ) + // Unit tests. + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..]\ + -C debuginfo=2 --test [..]", + ) + .run(); +} + +#[cargo_test] +fn targets_selected_all() { + let p = project().file("src/main.rs", "fn main() {}").build(); + // The first RUNNING is for unit tests + // The second RUNNING is for binaries + p.cargo("build -v --all-targets") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link [..]-C debuginfo=2 -[..]-test[..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn all_targets_no_lib() { + let p = project().file("src/main.rs", "fn main() {}").build(); + // The first RUNNING is for unit tests + // The second RUNNING is for binaries + p.cargo("build -v --all-targets") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..] -C debuginfo=2 [..]--test [..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn no_linkable_target() { + // Issue 3169: this is currently not an error as per discussion in PR #4797. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + [dependencies] + the_lib = { path = "the_lib" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "the_lib/Cargo.toml", + r#" + [package] + name = "the_lib" + version = "0.1.0" + edition = "2015" + [lib] + name = "the_lib" + crate-type = ["staticlib"] + "#, + ) + .file("the_lib/src/lib.rs", "pub fn foo() {}") + .build(); + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[WARNING] The package `the_lib` provides no linkable target. The compiler might raise an error while compiling `foo`. Consider adding 'dylib' or 'rlib' to key `crate-type` in `the_lib`'s Cargo.toml. This warning might turn into a hard error in the future. +[COMPILING] the_lib v0.1.0 ([ROOT]/foo/the_lib) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn avoid_dev_deps() { + Package::new("foo", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dev-dependencies] + baz = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `baz` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `bar v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); + p.cargo("build -Zavoid-dev-deps") + .masquerade_as_nightly_cargo(&["avoid-dev-deps"]) + .run(); +} + +#[cargo_test] +fn default_cargo_config_jobs() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + jobs = 1 + "#, + ) + .build(); + p.cargo("build -v").run(); +} + +#[cargo_test] +fn good_cargo_config_jobs() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + jobs = 4 + "#, + ) + .build(); + p.cargo("build -v").run(); +} + +#[cargo_test] +fn good_jobs() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build --jobs 1").run(); + + p.cargo("build --jobs -1").run(); + + p.cargo("build --jobs default").run(); +} + +#[cargo_test] +fn invalid_cargo_config_jobs() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + jobs = 0 + "#, + ) + .build(); + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] jobs may not be 0 + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_jobs() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build --jobs 0") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] jobs may not be 0 + +"#]]) + .run(); + + p.cargo("build --jobs over9000") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not parse `over9000`. Number of parallel jobs should be `default` or a number. + +"#]]) + .run(); +} + +#[cargo_test] +fn target_filters_workspace() { + let ws = project() + .at("ws") + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "") + .file("a/examples/ex1.rs", "fn main() {}") + .file("b/Cargo.toml", &basic_bin_manifest("b")) + .file("b/src/lib.rs", "") + .file("b/src/main.rs", "fn main() {}") + .build(); + + ws.cargo("build -v --example ex") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target named `ex` + +[HELP] a target with a similar name exists: `ex1` + +"#]]) + .run(); + + ws.cargo("build -v --example 'ex??'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target matches pattern `ex??` + +[HELP] a target with a similar name exists: `ex1` + +"#]]) + .run(); + + ws.cargo("build -v --lib") + .with_stderr_data( + str![[r#" +[COMPILING] a v0.5.0 ([ROOT]/ws/a) +[COMPILING] b v0.5.0 ([ROOT]/ws/b) +[RUNNING] `rustc [..]a/src/lib.rs[..]` +[RUNNING] `rustc [..]b/src/lib.rs[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + ws.cargo("build -v --example ex1") + .with_stderr_data(str![[r#" +[COMPILING] a v0.5.0 ([ROOT]/ws/a) +[RUNNING] `rustc [..]a/examples/ex1.rs[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn target_filters_workspace_not_found() { + let ws = project() + .at("ws") + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_bin_manifest("a")) + .file("a/src/main.rs", "fn main() {}") + .file("b/Cargo.toml", &basic_bin_manifest("b")) + .file("b/src/main.rs", "fn main() {}") + .build(); + + ws.cargo("build -v --lib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no library targets found in packages: a, b + +"#]]) + .run(); +} + +#[cfg(unix)] +#[cargo_test] +fn signal_display() { + // Cause the compiler to crash with a signal. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + pm = { path = "pm" } + "#, + ) + .file( + "src/lib.rs", + r#" + #[macro_use] + extern crate pm; + + #[derive(Foo)] + pub struct S; + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + [lib] + proc-macro = true + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Foo)] + pub fn derive(_input: TokenStream) -> TokenStream { + std::process::abort() + } + "#, + ) + .build(); + + foo.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] pm v0.1.0 ([ROOT]/foo/pm) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[ERROR] could not compile `foo` (lib) + +Caused by: + process didn't exit successfully: `rustc [..]` (signal: 6, SIGABRT: process abort signal) + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn tricky_pipelining() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + foo.cargo("build -p bar").run(); + foo.cargo("build -p foo").run(); +} + +#[cargo_test] +fn pipelining_works() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + foo.cargo("build") + .with_stdout_data(str![]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn pipelining_big_graph() { + // Create a crate graph of the form {a,b}{0..29}, where {a,b}(n) depend on {a,b}(n+1) + // Then have `foo`, a binary crate, depend on the whole thing. + let mut project = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + a1 = { path = "a1" } + b1 = { path = "b1" } + "#, + ) + .file("src/main.rs", "fn main(){}"); + + for n in 0..30 { + for x in &["a", "b"] { + project = project + .file( + &format!("{x}{n}/Cargo.toml", x = x, n = n), + &format!( + r#" + [package] + name = "{x}{n}" + version = "0.1.0" + edition = "2015" + [dependencies] + a{np1} = {{ path = "../a{np1}" }} + b{np1} = {{ path = "../b{np1}" }} + "#, + x = x, + n = n, + np1 = n + 1 + ), + ) + .file(&format!("{x}{n}/src/lib.rs", x = x, n = n), ""); + } + } + + let foo = project + .file("a30/Cargo.toml", &basic_lib_manifest("a30")) + .file( + "a30/src/lib.rs", + r#"compile_error!("don't actually build me");"#, + ) + .file("b30/Cargo.toml", &basic_lib_manifest("b30")) + .file("b30/src/lib.rs", "") + .build(); + foo.cargo("build -p foo") + .with_status(101) + .with_stderr_data( + str![[r#" +[COMPILING] a30 v0.5.0 ([ROOT]/foo/a30) +[ERROR] don't actually build me +... +[ERROR] could not compile `a30` (lib) due to 1 previous error +... + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn forward_rustc_output() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = '2018' + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "bar::foo!();") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + [lib] + proc-macro = true + "#, + ) + .file( + "bar/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::*; + + #[proc_macro] + pub fn foo(input: TokenStream) -> TokenStream { + println!("a"); + println!("b"); + println!("{{}}"); + eprintln!("c"); + eprintln!("d"); + eprintln!("{{a"); // "malformed json" + input + } + "#, + ) + .build(); + + foo.cargo("build") + .with_stdout_data(str![[r#" +a +b +{} + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +c +d +{a +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_lib_only() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("build --lib -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..] -L dependency=[ROOT]/foo/target/debug/deps` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_no_lib() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --lib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no library targets found in package `foo` + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_relative_cargo_home_path() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.0.1" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies] + + "test-dependency" = { path = "src/test_dependency" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/test_dependency/src/lib.rs", r#" "#) + .file( + "src/test_dependency/Cargo.toml", + &basic_manifest("test-dependency", "0.0.1"), + ) + .build(); + + p.cargo("build").env("CARGO_HOME", "./cargo_home/").run(); +} + +#[cargo_test] +fn user_specific_cfgs_are_filtered_out() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", r#"fn main() {}"#) + .file( + "build.rs", + r#" + fn main() { + assert!(std::env::var_os("CARGO_CFG_PROC_MACRO").is_none()); + assert!(std::env::var_os("CARGO_CFG_DEBUG_ASSERTIONS").is_none()); + } + "#, + ) + .build(); + + p.cargo("rustc -- --cfg debug_assertions --cfg proc_macro -Aunknown_lints -Aexplicit_builtin_cfgs_in_flags") + .run(); + p.process(&p.bin("foo")).run(); +} + +#[cargo_test] +fn close_output() { + // What happens when stdout or stderr is closed during a build. + + // Server to know when rustc has spawned. + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [lib] + proc-macro = true + + [[bin]] + name = "foobar" + "#, + ) + .file( + "src/lib.rs", + &r#" + use proc_macro::TokenStream; + use std::io::Read; + + #[proc_macro] + pub fn repro(_input: TokenStream) -> TokenStream { + println!("hello stdout!"); + eprintln!("hello stderr!"); + // Tell the test we have started. + let mut socket = std::net::TcpStream::connect("__ADDR__").unwrap(); + // Wait for the test to tell us to start printing. + let mut buf = [0]; + drop(socket.read_exact(&mut buf)); + let use_stderr = std::env::var("__CARGO_REPRO_STDERR").is_ok(); + // Emit at least 1MB of data. + // Linux pipes can buffer up to 64KB. + // This test seems to be sensitive to having other threads + // calling fork. My hypothesis is that the stdout/stderr + // file descriptors are duplicated into the child process, + // and during the short window between fork and exec, the + // file descriptor is kept alive long enough for the + // build to finish. It's a half-baked theory, but this + // seems to prevent the spurious errors in CI. + // An alternative solution is to run this test in + // a single-threaded environment. + for i in 0..100000 { + if use_stderr { + eprintln!("0123456789{}", i); + } else { + println!("0123456789{}", i); + } + } + TokenStream::new() + } + "# + .replace("__ADDR__", &addr.to_string()), + ) + .file( + "src/bin/foobar.rs", + r#" + foo::repro!(); + + fn main() {} + "#, + ) + .build(); + + // The `stderr` flag here indicates if this should forcefully close stderr or stdout. + let spawn = |stderr: bool| { + let mut cmd = p.cargo("build").build_command(); + cmd.stdout(Stdio::piped()).stderr(Stdio::piped()); + if stderr { + cmd.env("__CARGO_REPRO_STDERR", "1"); + } + let mut child = cmd.spawn().unwrap(); + // Wait for proc macro to start. + let pm_conn = listener.accept().unwrap().0; + // Close stderr or stdout. + if stderr { + drop(child.stderr.take()); + } else { + drop(child.stdout.take()); + } + // Tell the proc-macro to continue; + drop(pm_conn); + // Read the output from the other channel. + let out: &mut dyn Read = if stderr { + child.stdout.as_mut().unwrap() + } else { + child.stderr.as_mut().unwrap() + }; + let mut result = String::new(); + out.read_to_string(&mut result).unwrap(); + let status = child.wait().unwrap(); + assert!(!status.success()); + result + }; + + let stderr = spawn(false); + assert_e2e().eq( + &stderr, + str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +hello stderr! +[ERROR] [BROKEN_PIPE] +[WARNING] build failed, waiting for other jobs to finish... + +"#]] + .unordered(), + ); + + // Try again with stderr. + p.build_dir().rm_rf(); + let stdout = spawn(true); + assert_eq!(stdout, "hello stdout!\n"); +} + +#[cargo_test] +fn close_output_during_drain() { + // Test to close the output during the build phase (drain_the_queue). + // There was a bug where it would hang. + + // Server to know when rustc has spawned. + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + + // Create a wrapper so the test can know when compiling has started. + let rustc_wrapper = { + let p = project() + .at("compiler") + .file("Cargo.toml", &basic_manifest("compiler", "1.0.0")) + .file( + "src/main.rs", + &r#" + use std::process::Command; + use std::env; + use std::io::Read; + + fn main() { + // Only wait on the first dependency. + if matches!(env::var("CARGO_PKG_NAME").as_deref(), Ok("dep")) { + let mut socket = std::net::TcpStream::connect("__ADDR__").unwrap(); + // Wait for the test to tell us to start printing. + let mut buf = [0]; + drop(socket.read_exact(&mut buf)); + } + let mut cmd = Command::new("rustc"); + for arg in env::args_os().skip(1) { + cmd.arg(arg); + } + std::process::exit(cmd.status().unwrap().code().unwrap()); + } + "# + .replace("__ADDR__", &addr.to_string()), + ) + .build(); + p.cargo("build").run(); + p.bin("compiler") + }; + + Package::new("dep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Spawn cargo, wait for the first rustc to start, and then close stderr. + let mut cmd = process(&cargo_exe()) + .arg("check") + .cwd(p.root()) + .env("RUSTC", rustc_wrapper) + .build_command(); + cmd.stdout(Stdio::piped()).stderr(Stdio::piped()); + let mut child = cmd.spawn().expect("cargo should spawn"); + // Wait for the rustc wrapper to start. + let rustc_conn = listener.accept().unwrap().0; + // Close stderr to force an error. + drop(child.stderr.take()); + // Tell the wrapper to continue. + drop(rustc_conn); + match child.wait() { + Ok(status) => assert!(!status.success()), + Err(e) => panic!("child wait failed: {}", e), + } +} + +use cargo_test_support::registry::Dependency; + +#[cargo_test] +fn reduced_reproduction_8249() { + // https://github.com/rust-lang/cargo/issues/8249 + Package::new("a-src", "0.1.0").links("a").publish(); + Package::new("a-src", "0.2.0").links("a").publish(); + + Package::new("b", "0.1.0") + .add_dep(Dependency::new("a-src", "0.1").optional(true)) + .publish(); + Package::new("b", "0.2.0") + .add_dep(Dependency::new("a-src", "0.2").optional(true)) + .publish(); + + Package::new("c", "1.0.0") + .add_dep(&Dependency::new("b", "0.1.0")) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + b = { version = "*", features = ["a-src"] } + a-src = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + cargo_util::paths::append(&p.root().join("Cargo.toml"), b"c = \"*\"").unwrap(); + p.cargo("check").run(); + p.cargo("check").run(); +} + +#[cargo_test] +fn target_directory_backup_exclusion() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + // Newly created target/ should have CACHEDIR.TAG inside... + p.cargo("build").run(); + let cachedir_tag = p.build_dir().join("CACHEDIR.TAG"); + assert!(cachedir_tag.is_file()); + assert!(fs::read_to_string(&cachedir_tag) + .unwrap() + .starts_with("Signature: 8a477f597d28d172789f06886806bc55")); + // ...but if target/ already exists CACHEDIR.TAG should not be created in it. + fs::remove_file(&cachedir_tag).unwrap(); + p.cargo("build").run(); + assert!(!&cachedir_tag.is_file()); +} + +#[cargo_test] +fn simple_terminal_width() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() { + let _: () = 42; + } + "#, + ) + .build(); + + p.cargo("build -v") + .env("__CARGO_TEST_TTY_WIDTH_DO_NOT_USE_THIS", "20") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]--diagnostic-width=20[..] +error[E0308][..] +... +[ERROR] could not compile `foo` (lib) due to 1 previous error + +Caused by: + process didn't exit successfully: `rustc [..]` ([EXIT_STATUS]: 1) + +"#]]) + .run(); + + p.cargo("doc -v") + .env("__CARGO_TEST_TTY_WIDTH_DO_NOT_USE_THIS", "20") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..]--diagnostic-width=20[..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn build_script_o0_default() { + let p = project() + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("build -v --release") + .with_stderr_does_not_contain("[..]build_script_build[..]opt-level[..]") + .run(); +} + +#[cargo_test] +fn build_script_o0_default_even_with_release() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.release] + opt-level = 1 + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("build -v --release") + .with_stderr_does_not_contain("[..]build_script_build[..]opt-level[..]") + .run(); +} + +#[cargo_test] +fn primary_package_env_var() { + // Test that CARGO_PRIMARY_PACKAGE is enabled only for "foo" and not for any dependency. + + let is_primary_package = r#" + pub fn is_primary_package() -> bool {{ + option_env!("CARGO_PRIMARY_PACKAGE").is_some() + }} + "#; + + Package::new("qux", "0.1.0") + .file("src/lib.rs", is_primary_package) + .publish(); + + let baz = git::new("baz", |project| { + project + .file("Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("src/lib.rs", is_primary_package) + }); + + let foo = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ path = "bar" }} + baz = {{ git = '{}' }} + qux = "0.1" + "#, + baz.url() + ), + ) + .file( + "src/lib.rs", + &format!( + r#" + extern crate bar; + extern crate baz; + extern crate qux; + + {} + + #[test] + fn verify_primary_package() {{ + assert!(!bar::is_primary_package()); + assert!(!baz::is_primary_package()); + assert!(!qux::is_primary_package()); + assert!(is_primary_package()); + }} + "#, + is_primary_package + ), + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", is_primary_package) + .build(); + + foo.cargo("test").run(); +} + +#[cargo_test] +fn renamed_uplifted_artifact_remains_unmodified_after_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); + + let bin = p.bin("foo"); + let renamed_bin = p.bin("foo-renamed"); + + fs::rename(&bin, &renamed_bin).unwrap(); + + p.change_file("src/main.rs", "fn main() { eprintln!(\"hello, world\"); }"); + p.cargo("build").run(); + + let not_the_same = !same_file::is_same_file(bin, renamed_bin).unwrap(); + assert!(not_the_same, "renamed uplifted artifact must be unmodified"); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_plan.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_plan.rs new file mode 100644 index 000000000..d6eaf87fd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_plan.rs @@ -0,0 +1,244 @@ +//! Tests for --build-plan feature. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_bin_manifest, basic_manifest, main_file, project, str}; + +#[cargo_test] +fn cargo_build_plan_simple() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build --build-plan -Zunstable-options") + .masquerade_as_nightly_cargo(&["build-plan"]) + .with_stdout_data( + str![[r#" +{ + "inputs": [ + "[ROOT]/foo/Cargo.toml" + ], + "invocations": [ + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [], + "env": "{...}", + "kind": null, + "links": "{...}", + "outputs": "{...}", + "package_name": "foo", + "package_version": "0.5.0", + "program": "rustc", + "target_kind": [ + "bin" + ] + } + ] +} +"#]] + .is_json(), + ) + .run(); + assert!(!p.bin("foo").is_file()); +} + +#[cargo_test] +fn cargo_build_plan_single_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.5.0" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + pub fn foo() { bar::bar(); } + + #[test] + fn test() { foo(); } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + p.cargo("build --build-plan -Zunstable-options") + .masquerade_as_nightly_cargo(&["build-plan"]) + .with_stdout_data( + str![[r#" +{ + "inputs": [ + "[ROOT]/foo/Cargo.toml", + "[ROOT]/foo/bar/Cargo.toml" + ], + "invocations": [ + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [], + "env": "{...}", + "kind": null, + "links": {}, + "outputs": [ + "[ROOT]/foo/target/debug/deps/libbar-[HASH].rlib", + "[ROOT]/foo/target/debug/deps/libbar-[HASH].rmeta" + ], + "package_name": "bar", + "package_version": "0.0.1", + "program": "rustc", + "target_kind": [ + "lib" + ] + }, + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [ + 0 + ], + "env": "{...}", + "kind": null, + "links": "{...}", + "outputs": [ + "[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib", + "[ROOT]/foo/target/debug/deps/libfoo-[HASH].rmeta" + ], + "package_name": "foo", + "package_version": "0.5.0", + "program": "rustc", + "target_kind": [ + "lib" + ] + } + ] +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_build_plan_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + build = "build.rs" + "#, + ) + .file("src/main.rs", r#"fn main() {}"#) + .file("build.rs", r#"fn main() {}"#) + .build(); + + p.cargo("build --build-plan -Zunstable-options") + .masquerade_as_nightly_cargo(&["build-plan"]) + .with_stdout_data( + str![[r#" +{ + "inputs": [ + "[ROOT]/foo/Cargo.toml" + ], + "invocations": [ + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [], + "env": "{...}", + "kind": null, + "links": "{...}", + "outputs": "{...}", + "package_name": "foo", + "package_version": "0.5.0", + "program": "rustc", + "target_kind": [ + "custom-build" + ] + }, + { + "args": "{...}", + "compile_mode": "run-custom-build", + "cwd": "[ROOT]/foo", + "deps": [ + 0 + ], + "env": "{...}", + "kind": null, + "links": {}, + "outputs": [], + "package_name": "foo", + "package_version": "0.5.0", + "program": "[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build", + "target_kind": [ + "custom-build" + ] + }, + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [ + 1 + ], + "env": "{...}", + "kind": null, + "links": "{...}", + "outputs": "{...}", + "package_name": "foo", + "package_version": "0.5.0", + "program": "rustc", + "target_kind": [ + "bin" + ] + } + ] +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn build_plan_with_dev_dep() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + authors = [] + + [dev-dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --build-plan -Zunstable-options") + .masquerade_as_nightly_cargo(&["build-plan"]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script.rs new file mode 100644 index 000000000..a072d567f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script.rs @@ -0,0 +1,6089 @@ +//! Tests for build.rs scripts. + +use std::env; +use std::fs; +use std::io; +use std::thread; + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::paths::cargo_home; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::tools; +use cargo_test_support::{ + basic_manifest, cargo_exe, cross_compile, is_coarse_mtime, project, project_in, +}; +use cargo_test_support::{git, rustc_host, sleep_ms, slow_cpu_multiplier, symlink_supported}; +use cargo_util::paths::{self, remove_dir_all}; + +#[cargo_test] +fn custom_build_script_failed() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("build.rs", "fn main() { std::process::exit(101); }") + .build(); + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101) + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_script_failed_backtraces_message() { + // In this situation (no dependency sharing), debuginfo is turned off in + // `dev.build-override`. However, if an error occurs running e.g. a build + // script, and backtraces are opted into: a message explaining how to + // improve backtraces is also displayed. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("build.rs", "fn main() { std::process::exit(101); }") + .build(); + p.cargo("build -v") + .env("RUST_BACKTRACE", "1") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)` +[NOTE] To improve backtraces for build dependencies, set the CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG=true environment variable to enable debug information generation. + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101) + +"#]]) + .run(); + + p.cargo("check -v") + .env("RUST_BACKTRACE", "1") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)` +[NOTE] To improve backtraces for build dependencies, set the CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG=true environment variable to enable debug information generation. + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101) + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_script_failed_backtraces_message_with_debuginfo() { + // This is the same test as `custom_build_script_failed_backtraces_message` above, this time + // ensuring that the message dedicated to improving backtraces by requesting debuginfo is not + // shown when debuginfo is already turned on. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("build.rs", "fn main() { std::process::exit(101); }") + .build(); + p.cargo("build -v") + .env("RUST_BACKTRACE", "1") + .env("CARGO_PROFILE_DEV_BUILD_OVERRIDE_DEBUG", "true") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101) + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_env_vars() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [features] + bar_feat = ["bar/foo", "bar/other-feature"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + + [features] + foo = [] + other-feature = [] + "#, + ) + .file("bar/src/lib.rs", "pub fn hello() {}"); + + let cargo = cargo_exe().canonicalize().unwrap(); + let cargo = cargo.to_str().unwrap(); + let rustc = paths::resolve_executable("rustc".as_ref()) + .unwrap() + .canonicalize() + .unwrap(); + let rustc = rustc.to_str().unwrap(); + let file_content = format!( + r##" + use std::env; + use std::path::Path; + + fn main() {{ + let _target = env::var("TARGET").unwrap(); + let _ncpus = env::var("NUM_JOBS").unwrap(); + let _dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + + let opt = env::var("OPT_LEVEL").unwrap(); + assert_eq!(opt, "0"); + + let opt = env::var("PROFILE").unwrap(); + assert_eq!(opt, "debug"); + + let debug = env::var("DEBUG").unwrap(); + assert_eq!(debug, "true"); + + let out = env::var("OUT_DIR").unwrap(); + assert!(out.starts_with(r"{0}")); + assert!(Path::new(&out).is_dir()); + + let _host = env::var("HOST").unwrap(); + + let _feat = env::var("CARGO_FEATURE_FOO").unwrap(); + let feat = env::var("CARGO_CFG_FEATURE").unwrap(); + assert_eq!(feat, "foo,other-feature"); + + let cargo = env::var("CARGO").unwrap(); + if env::var_os("CHECK_CARGO_IS_RUSTC").is_some() {{ + assert_eq!(cargo, r#"{rustc}"#); + }} else {{ + assert_eq!(cargo, r#"{cargo}"#); + }} + + let rustc = env::var("RUSTC").unwrap(); + assert_eq!(rustc, "rustc"); + + let rustdoc = env::var("RUSTDOC").unwrap(); + assert_eq!(rustdoc, "rustdoc"); + + assert!(env::var("RUSTC_WRAPPER").is_err()); + assert!(env::var("RUSTC_WORKSPACE_WRAPPER").is_err()); + + assert!(env::var("RUSTC_LINKER").is_err()); + + assert!(env::var("RUSTFLAGS").is_err()); + let rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(); + assert_eq!(rustflags, ""); + }} + "##, + p.root() + .join("target") + .join("debug") + .join("build") + .display(), + ); + + let p = p.file("bar/build.rs", &file_content).build(); + + p.cargo("build --features bar_feat").run(); + p.cargo("build --features bar_feat") + // we use rustc since $CARGO is only used if it points to a path that exists + .env("CHECK_CARGO_IS_RUSTC", "1") + .env(cargo::CARGO_ENV, rustc) + .run(); +} + +#[cargo_test] +fn custom_build_env_var_rustflags() { + let rustflags = "--cfg=special"; + let rustflags_alt = "--cfg=notspecial"; + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [build] + rustflags = ["{}"] + "#, + rustflags + ), + ) + .file( + "build.rs", + &format!( + r#" + use std::env; + + fn main() {{ + // Static assertion that exactly one of the cfg paths is always taken. + assert!(env::var("RUSTFLAGS").is_err()); + let x; + #[cfg(special)] + {{ assert_eq!(env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(), "{}"); x = String::new(); }} + #[cfg(notspecial)] + {{ assert_eq!(env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(), "{}"); x = String::new(); }} + let _ = x; + }} + "#, + rustflags, rustflags_alt, + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + // RUSTFLAGS overrides build.rustflags, so --cfg=special shouldn't be passed + p.cargo("check").env("RUSTFLAGS", rustflags_alt).run(); +} + +#[cargo_test] +fn custom_build_env_var_encoded_rustflags() { + // NOTE: We use "-Clink-arg=-B nope" here rather than, say, "-A missing_docs", since for the + // latter it won't matter if the whitespace accidentally gets split, as rustc will do the right + // thing either way. + let p = project() + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["-Clink-arg=-B nope", "--cfg=foo"] + "#, + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() {{ + assert_eq!(env::var("CARGO_ENCODED_RUSTFLAGS").unwrap(), "-Clink-arg=-B nope\x1f--cfg=foo"); + }} + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn custom_build_env_var_rustc_wrapper() { + let wrapper = tools::echo_wrapper(); + let p = project() + .file( + "build.rs", + r#" + use std::env; + + fn main() {{ + assert_eq!( + env::var("RUSTC_WRAPPER").unwrap(), + env::var("CARGO_RUSTC_WRAPPER_CHECK").unwrap() + ); + }} + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .env("CARGO_BUILD_RUSTC_WRAPPER", &wrapper) + .env("CARGO_RUSTC_WRAPPER_CHECK", &wrapper) + .run(); +} + +#[cargo_test] +fn custom_build_env_var_rustc_workspace_wrapper() { + let wrapper = tools::echo_wrapper(); + + // Workspace wrapper should be set for any crate we're operating directly on. + let p = project() + .file( + "build.rs", + r#" + use std::env; + + fn main() {{ + assert_eq!( + env::var("RUSTC_WORKSPACE_WRAPPER").unwrap(), + env::var("CARGO_RUSTC_WORKSPACE_WRAPPER_CHECK").unwrap() + ); + }} + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .env("CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER", &wrapper) + .env("CARGO_RUSTC_WORKSPACE_WRAPPER_CHECK", &wrapper) + .run(); + + // But should not be set for a crate from the registry, as then it's not in a workspace. + Package::new("bar", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + links = "a" + "#, + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() {{ + assert!(env::var("RUSTC_WORKSPACE_WRAPPER").is_err()); + }} + "#, + ) + .file("src/lib.rs", "") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .env("CARGO_BUILD_RUSTC_WORKSPACE_WRAPPER", &wrapper) + .run(); +} + +#[cargo_test] +fn custom_build_env_var_rustc_linker() { + if cross_compile::disabled() { + return; + } + let target = cross_compile::alternate(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + linker = "/path/to/linker" + "#, + target + ), + ) + .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(); +} + +// 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.toml", + 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(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + linker = "/path/to/linker" + "#, + target + ), + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + // build.rs should fail since host == target when no target is set + p.cargo("build --verbose") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/linker [..]` +[ERROR] linker `[..]/path/to/linker` not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_env_var_rustc_linker_host_target() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + target-applies-to-host = false + [target.{}] + linker = "/path/to/linker" + "#, + target + ), + ) + .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 -Z target-applies-to-host --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .run(); +} + +#[cargo_test] +fn custom_build_env_var_rustc_linker_host_target_env() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + linker = "/path/to/linker" + "#, + target + ), + ) + .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 -Z target-applies-to-host --target") + .env("CARGO_TARGET_APPLIES_TO_HOST", "false") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .run(); +} + +#[cargo_test] +fn custom_build_invalid_host_config_feature_flag() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + linker = "/path/to/linker" + "#, + target + ), + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + // build.rs should fail due to -Zhost-config being set without -Ztarget-applies-to-host + p.cargo("build -Z host-config --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["host-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the -Zhost-config flag requires the -Ztarget-applies-to-host flag to be set + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_linker_host_target_with_bad_host_config() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [host] + linker = "/path/to/host/linker" + [target.{}] + linker = "/path/to/target/linker" + "#, + target + ), + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + // build.rs should fail due to bad host linker being set + p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/host/linker [..]` +[ERROR] linker `[..]/path/to/host/linker` not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_linker_bad_host() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [host] + linker = "/path/to/host/linker" + [target.{}] + linker = "/path/to/target/linker" + "#, + target + ), + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + // build.rs should fail due to bad host linker being set + p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/host/linker [..]` +[ERROR] linker `[..]/path/to/host/linker` not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_linker_bad_host_with_arch() { + let target = rustc_host(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [host] + linker = "/path/to/host/linker" + [host.{}] + linker = "/path/to/host/arch/linker" + [target.{}] + linker = "/path/to/target/linker" + "#, + target, target + ), + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + // build.rs should fail due to bad host linker being set + p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..]-C linker=[..]/path/to/host/arch/linker [..]` +[ERROR] linker `[..]/path/to/host/arch/linker` not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_env_var_rustc_linker_cross_arch_host() { + let target = rustc_host(); + let cross_target = cross_compile::alternate(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [host.{}] + linker = "/path/to/host/arch/linker" + [target.{}] + linker = "/path/to/target/linker" + "#, + cross_target, target + ), + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert!(env::var("RUSTC_LINKER").unwrap().ends_with("/path/to/target/linker")); + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // build.rs should be built fine since cross target != host target. + // assertion should succeed since it's still passed the target linker + p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .run(); +} + +#[cargo_test] +fn custom_build_linker_bad_cross_arch_host() { + let target = rustc_host(); + let cross_target = cross_compile::alternate(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [host] + linker = "/path/to/host/linker" + [host.{}] + linker = "/path/to/host/arch/linker" + [target.{}] + linker = "/path/to/target/linker" + "#, + cross_target, target + ), + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + // build.rs should fail due to bad host linker being set + p.cargo("build -Z target-applies-to-host -Z host-config --verbose --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin [..] -C linker=[..]/path/to/host/linker [..]` +[ERROR] linker `[..]/path/to/host/linker` not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_script_wrong_rustc_flags() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-flags=-aaa -bbb"); }"#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[ERROR] Only `-l` and `-L` flags are allowed in build script of `foo v0.5.0 ([ROOT]/foo)`: `-aaa -bbb` + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_script_rustc_flags() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.foo] + path = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "foo/Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "foo/build.rs", + r#" + fn main() { + let root = std::env::current_dir().unwrap(); + let root = root.parent().unwrap(); + println!("cargo::rustc-flags=-l nonexistinglib \ + -L {R}/dummy-path1 -L {R}/dummy-path2", R=root.display()); + } + "#, + ) + .build(); + p.root().join("dummy-path1").mkdir_p(); + p.root().join("dummy-path2").mkdir_p(); + + p.cargo("build --verbose") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.5.0 ([ROOT]/foo/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 foo/build.rs [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo --edition=2015 foo/src/lib.rs [..]-L dependency=[ROOT]/foo/target/debug/deps -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2 -l nonexistinglib` +[COMPILING] bar v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bar --edition=2015 src/main.rs [..]-L dependency=[ROOT]/foo/target/debug/deps --extern foo=[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn custom_build_script_rustc_flags_no_space() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.foo] + path = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "foo/Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "foo/build.rs", + r#" + fn main() { + let root = std::env::current_dir().unwrap(); + let root = root.parent().unwrap(); + println!("cargo::rustc-flags=-lnonexistinglib \ + -L {R}/dummy-path1 -L {R}/dummy-path2", R=root.display()); + } + "#, + ) + .build(); + p.root().join("dummy-path1").mkdir_p(); + p.root().join("dummy-path2").mkdir_p(); + + p.cargo("build --verbose").with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.5.0 ([ROOT]/foo/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 foo/build.rs [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo --edition=2015 foo/src/lib.rs [..]-L dependency=[ROOT]/foo/target/debug/deps -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2 -l nonexistinglib` +[COMPILING] bar v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bar --edition=2015 src/main.rs [..]-L dependency=[ROOT]/foo/target/debug/deps --extern foo=[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib -L [ROOT]/foo/dummy-path1 -L [ROOT]/foo/dummy-path2` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn links_no_build_cmd() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + package specifies that it links to `a` but does not have a custom build script + +"#]]) + .run(); +} + +#[cargo_test] +fn links_duplicates() { + // this tests that the links_duplicates are caught at resolver time + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + + [dependencies.a-sys] + path = "a-sys" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "") + .file( + "a-sys/Cargo.toml", + r#" + [package] + name = "a-sys" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + "#, + ) + .file("a-sys/src/lib.rs", "") + .file("a-sys/build.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to select a version for `a-sys`. + ... required by package `foo v0.5.0 ([ROOT]/foo)` +versions that meet the requirements `*` are: 0.5.0 + +the package `a-sys` links to the native library `a`, but it conflicts with a previous package which links to `a` as well: +package `foo v0.5.0 ([ROOT]/foo)` +Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = "a"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links. + +failed to select a version for `a-sys` which could resolve this conflict + +"#]]) + .run(); +} + +#[cargo_test] +fn links_duplicates_old_registry() { + // Test old links validator. See `validate_links`. + Package::new("bar", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + links = "a" + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + links = "a" + + [dependencies] + bar = "0.1" + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[ERROR] multiple packages link to native library `a`, but a native library can be linked only once + +package `bar v0.1.0` + ... which satisfies dependency `bar = "^0.1"` (locked to 0.1.0) of package `foo v0.1.0 ([ROOT]/foo)` +links to native library `a` + +package `foo v0.1.0 ([ROOT]/foo)` +also links to native library `a` + +"#]]) + .run(); +} + +#[cargo_test] +fn links_duplicates_deep_dependency() { + // this tests that the links_duplicates are caught at resolver time + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.a-sys] + path = "a-sys" + "#, + ) + .file("a/src/lib.rs", "") + .file("a/build.rs", "") + .file( + "a/a-sys/Cargo.toml", + r#" + [package] + name = "a-sys" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + "#, + ) + .file("a/a-sys/src/lib.rs", "") + .file("a/a-sys/build.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to select a version for `a-sys`. + ... required by package `a v0.5.0 ([ROOT]/foo/a)` + ... which satisfies path dependency `a` of package `foo v0.5.0 ([ROOT]/foo)` +versions that meet the requirements `*` are: 0.5.0 + +the package `a-sys` links to the native library `a`, but it conflicts with a previous package which links to `a` as well: +package `foo v0.5.0 ([ROOT]/foo)` +Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = "a"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links. + +failed to select a version for `a-sys` which could resolve this conflict + +"#]]) + .run(); +} + +#[cargo_test] +fn overrides_and_links() { + let target = rustc_host(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + fn main() { + assert_eq!(env::var("DEP_FOO_FOO").ok().expect("FOO missing"), + "bar"); + assert_eq!(env::var("DEP_FOO_BAR").ok().expect("BAR missing"), + "baz"); + } + "#, + ) + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.foo] + rustc-flags = "-L foo -L bar" + foo = "bar" + bar = "baz" + "#, + target + ), + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("a/src/lib.rs", "") + .file("a/build.rs", "not valid rust code") + .build(); + + p.cargo("build -v") + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] a v0.5.0 ([ROOT]/foo/a) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `rustc --crate-name a [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] -L foo -L bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn unused_overrides() { + let target = rustc_host(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.foo] + rustc-flags = "-L foo -L bar" + foo = "bar" + bar = "baz" + "#, + target + ), + ) + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn links_passes_env_vars() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + fn main() { + assert_eq!(env::var("DEP_FOO_FOO").unwrap(), "bar"); + assert_eq!(env::var("DEP_FOO_BAR").unwrap(), "baz"); + } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + r#" + use std::env; + fn main() { + let lib = env::var("CARGO_MANIFEST_LINKS").unwrap(); + assert_eq!(lib, "foo"); + + println!("cargo::metadata=foo=bar"); + println!("cargo::metadata=bar=baz"); + } + "#, + ) + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn only_rerun_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("build -v").run(); + p.root().move_into_the_past(); + + p.change_file("some-new-file", ""); + p.root().move_into_the_past(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rebuild_continues_to_pass_env_vars() { + let a = project() + .at("a") + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::time::Duration; + fn main() { + println!("cargo::metadata=foo=bar"); + println!("cargo::metadata=bar=baz"); + std::thread::sleep(Duration::from_millis(500)); + } + "#, + ) + .build(); + a.root().move_into_the_past(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.a] + path = '{}' + "#, + a.root().display() + ), + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + fn main() { + assert_eq!(env::var("DEP_FOO_FOO").unwrap(), "bar"); + assert_eq!(env::var("DEP_FOO_BAR").unwrap(), "baz"); + } + "#, + ) + .build(); + + p.cargo("build -v").run(); + p.root().move_into_the_past(); + + p.change_file("some-new-file", ""); + p.root().move_into_the_past(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn testing_and_such() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + println!("build"); + p.cargo("build -v").run(); + p.root().move_into_the_past(); + + p.change_file("src/lib.rs", ""); + p.root().move_into_the_past(); + + println!("test"); + p.cargo("test -vj1") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc [..]--test [..]` + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + println!("doc"); + p.cargo("doc -v") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustdoc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + p.change_file("src/main.rs", "fn main() {}"); + println!("run"); + p.cargo("run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn propagation_of_l_flags() { + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "bar" + build = "build.rs" + + [dependencies.b] + path = "../b" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + r#"fn main() { println!("cargo::rustc-flags=-L bar"); }"#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("b/src/lib.rs", "") + .file("b/build.rs", "bad file") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.foo] + rustc-flags = "-L foo" + "#, + target + ), + ) + .build(); + + p.cargo("build -v -j1") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustc --crate-name a [..] -L bar -L foo` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -L bar -L foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn propagation_of_l_flags_new() { + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "bar" + build = "build.rs" + + [dependencies.b] + path = "../b" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=bar"); + } + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("b/src/lib.rs", "") + .file("b/build.rs", "bad file") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.foo] + rustc-link-search = ["foo"] + "#, + target + ), + ) + .build(); + + p.cargo("build -v -j1") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustc --crate-name a [..] -L bar -L foo` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -L bar -L foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_deps_simple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + [build-dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + " + #[allow(unused_extern_crates)] + extern crate a; + fn main() {} + ", + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.5.0")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build -v").with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] a v0.5.0 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name a [..]` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..] build.rs [..] --extern a=[ROOT]/foo/target/debug/deps/liba-[HASH].rlib` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn build_deps_not_for_normal() { + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + [build-dependencies.aaaaa] + path = "a" + "#, + ) + .file( + "src/lib.rs", + "#[allow(unused_extern_crates)] extern crate aaaaa;", + ) + .file( + "build.rs", + " + #[allow(unused_extern_crates)] + extern crate aaaaa; + fn main() {} + ", + ) + .file("a/Cargo.toml", &basic_manifest("aaaaa", "0.5.0")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build -v --target") + .arg(&target) + .with_status(101) + .with_stderr_data( + str![[r#" +... +error[E0463]: can't find crate for `aaaaa` +[ERROR] could not compile `foo` (lib) due to 1 previous error + +Caused by: + process didn't exit successfully: `rustc --crate-name foo[..]` ([EXIT_STATUS]: 1) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_cmd_with_a_build_cmd() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [build-dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + " + #[allow(unused_extern_crates)] + extern crate a; + fn main() {} + ", + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [build-dependencies.b] + path = "../b" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + "#[allow(unused_extern_crates)] extern crate b; fn main() {}", + ) + .file("b/Cargo.toml", &basic_manifest("b", "0.5.0")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build -v").with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] b v0.5.0 ([ROOT]/foo/b) +[RUNNING] `rustc --crate-name b [..]` +[COMPILING] a v0.5.0 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name build_script_build [..] a/build.rs [..] --extern b=[ROOT]/foo/target/debug/deps/libb-[HASH].rlib` +[RUNNING] `[ROOT]/foo/target/debug/build/a-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name a [..]a/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] -L dependency=[ROOT]/foo/target/debug/deps --extern a=[ROOT]/foo/target/debug/deps/liba-[HASH].rlib` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn out_dir_is_preserved() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + use std::fs::File; + use std::path::Path; + fn main() { + let out = env::var("OUT_DIR").unwrap(); + File::create(Path::new(&out).join("foo")).unwrap(); + } + "#, + ) + .build(); + + // Make the file + p.cargo("build -v").run(); + + // Change to asserting that it's there + p.change_file( + "build.rs", + r#" + use std::env; + use std::fs::File; + use std::path::Path; + fn main() { + let out = env::var("OUT_DIR").unwrap(); + File::open(&Path::new(&out).join("foo")).unwrap(); + } + "#, + ); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `build.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Run a fresh build where file should be preserved + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // One last time to make sure it's still there. + p.change_file("foo", ""); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn output_separate_lines() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-flags=-L foo"); + println!("cargo::rustc-flags=-l static=foo"); + } + "#, + ) + .build(); + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] -L foo -l static=foo` +[ERROR] could not find native static library `foo`, perhaps an -L flag is missing? +... +"#]]) + .run(); +} + +#[cargo_test] +fn output_separate_lines_new() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=foo"); + println!("cargo::rustc-link-lib=static=foo"); + println!("cargo::rustc-link-lib=bar"); + println!("cargo::rustc-link-search=bar"); + } + "#, + ) + .build(); + // The order of the arguments passed to rustc is important. + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] -L foo -L bar -l static=foo -l bar` +[ERROR] could not find native static library `foo`, perhaps an -L flag is missing? +... +"#]]) + .run(); +} + +#[cargo_test] +fn code_generation() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "src/main.rs", + r#" + include!(concat!(env!("OUT_DIR"), "/hello.rs")); + + fn main() { + println!("{}", message()); + } + "#, + ) + .file( + "build.rs", + r#" + use std::env; + use std::fs; + use std::path::PathBuf; + + fn main() { + let dst = PathBuf::from(env::var("OUT_DIR").unwrap()); + fs::write(dst.join("hello.rs"), + " + pub fn message() -> &'static str { + \"Hello, World!\" + } + ") + .unwrap(); + } + "#, + ) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +Hello, World! + +"#]]) + .run(); + + p.cargo("test").run(); +} + +#[cargo_test] +fn release_with_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() {} + "#, + ) + .build(); + + p.cargo("build -v --release").run(); +} + +#[cargo_test] +fn build_script_only() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("build.rs", r#"fn main() {}"#) + .build(); + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + no targets specified in the manifest + either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present + +"#]]) + .run(); +} + +#[cargo_test] +fn shared_dep_with_a_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.a] + path = "a" + + [build-dependencies.b] + path = "b" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("a/build.rs", "fn main() {}") + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies.a] + path = "../a" + "#, + ) + .file("b/src/lib.rs", "") + .build(); + p.cargo("build -v").run(); +} + +#[cargo_test] +fn test_a_lib_with_a_build_command() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "src/lib.rs", + r#" + include!(concat!(env!("OUT_DIR"), "/foo.rs")); + + /// ``` + /// foo::bar(); + /// ``` + pub fn bar() { + assert_eq!(foo(), 1); + } + "#, + ) + .file( + "build.rs", + r#" + use std::env; + use std::fs; + use std::path::PathBuf; + + fn main() { + let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + fs::write(out.join("foo.rs"), "fn foo() -> i32 { 1 }").unwrap(); + } + "#, + ) + .build(); + p.cargo("test").run(); +} + +#[cargo_test] +fn test_dev_dep_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dev-dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("a/build.rs", "fn main() {}") + .file("a/src/lib.rs", "") + .build(); + + p.cargo("test").run(); +} + +#[cargo_test] +fn build_script_with_dynamic_native_dependency() { + let build = project() + .at("builder") + .file( + "Cargo.toml", + r#" + [package] + name = "builder" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "builder" + crate-type = ["dylib"] + "#, + ) + .file("src/lib.rs", r#"#[no_mangle] pub extern "C" fn foo() {}"#) + .build(); + + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + + [build-dependencies.bar] + path = "bar" + "#, + ) + .file("build.rs", "extern crate bar; fn main() { bar::bar() }") + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "bar/build.rs", + r#" + use std::env; + use std::fs; + use std::path::PathBuf; + + fn main() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let root = PathBuf::from(env::var("BUILDER_ROOT").unwrap()); + let file = format!("{}builder{}", + env::consts::DLL_PREFIX, + env::consts::DLL_SUFFIX); + let src = root.join(&file); + let dst = out_dir.join(&file); + fs::copy(src, dst).unwrap(); + if cfg!(target_env = "msvc") { + fs::copy(root.join("builder.dll.lib"), + out_dir.join("builder.dll.lib")).unwrap(); + } + println!("cargo::rustc-link-search=native={}", out_dir.display()); + } + "#, + ) + .file( + "bar/src/lib.rs", + r#" + pub fn bar() { + #[cfg_attr(not(target_env = "msvc"), link(name = "builder"))] + #[cfg_attr(target_env = "msvc", link(name = "builder.dll"))] + extern "C" { fn foo(); } + unsafe { foo() } + } + "#, + ) + .build(); + + build + .cargo("build -v") + .env("CARGO_LOG", "cargo::ops::cargo_rustc") + .run(); + + let root = build.root().join("target").join("debug"); + foo.cargo("build -v") + .env("BUILDER_ROOT", root) + .env("CARGO_LOG", "cargo::ops::cargo_rustc") + .run(); +} + +#[cargo_test] +fn profile_and_opt_level_set_correctly() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert_eq!(env::var("OPT_LEVEL").unwrap(), "3"); + assert_eq!(env::var("PROFILE").unwrap(), "release"); + assert_eq!(env::var("DEBUG").unwrap(), "false"); + } + "#, + ) + .build(); + p.cargo("bench").run(); +} + +#[cargo_test] +fn profile_debug_0() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + debug = 0 + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert_eq!(env::var("OPT_LEVEL").unwrap(), "0"); + assert_eq!(env::var("PROFILE").unwrap(), "debug"); + assert_eq!(env::var("DEBUG").unwrap(), "false"); + } + "#, + ) + .build(); + p.cargo("build").run(); +} + +#[cargo_test] +fn build_script_with_lto() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + + [profile.dev] + lto = true + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + p.cargo("build").run(); +} + +#[cargo_test] +fn test_duplicate_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.bar] + path = "bar" + + [build-dependencies.bar] + path = "bar" + "#, + ) + .file( + "src/main.rs", + r#" + extern crate bar; + fn main() { bar::do_nothing() } + "#, + ) + .file( + "build.rs", + r#" + extern crate bar; + fn main() { bar::do_nothing() } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn do_nothing() {}") + .build(); + + p.cargo("build").run(); +} + +#[cargo_test] +fn cfg_feedback() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/main.rs", "#[cfg(foo)] fn main() {}") + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-cfg=foo"); }"#, + ) + .build(); + p.cargo("build -v").run(); +} + +#[cargo_test] +fn cfg_override() { + let target = rustc_host(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + "#, + ) + .file("src/main.rs", "#[cfg(foo)] fn main() {}") + .file("build.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.a] + rustc-cfg = ["foo"] + "#, + target + ), + ) + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn cfg_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#"fn main() { + println!("cargo::rustc-cfg=foo"); + println!("cargo::rustc-check-cfg=cfg(foo)"); + }"#, + ) + .file( + "src/lib.rs", + r#" + /// + /// ``` + /// extern crate foo; + /// + /// fn main() { + /// foo::foo() + /// } + /// ``` + /// + #[cfg(foo)] + pub fn foo() {} + + #[cfg(foo)] + #[test] + fn test_foo() { + foo() + } + "#, + ) + .file("tests/test.rs", "#[cfg(foo)] #[test] fn test_bar() {}") + .build(); + p.cargo("test -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] --cfg foo[..]` +[RUNNING] `rustc --crate-name foo [..] --cfg foo[..]` +[RUNNING] `rustc --crate-name test [..] --cfg foo[..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/debug/deps/test-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc [..]--cfg foo[..]` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test_foo ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test_bar ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test src/lib.rs - foo (line 3) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-cfg=foo"); }"#, + ) + .file("src/lib.rs", "#[cfg(foo)] pub fn foo() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "bar/build.rs", + r#"fn main() { println!("cargo::rustc-cfg=bar"); }"#, + ) + .file("bar/src/lib.rs", "#[cfg(bar)] pub fn bar() {}") + .build(); + p.cargo("doc").run(); + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/fn.foo.html").is_file()); + assert!(p.root().join("target/doc/bar/fn.bar.html").is_file()); +} + +#[cargo_test] +fn cfg_override_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + links = "a" + + [lints.rust] + unexpected_cfgs = "allow" # bc of override, stable/nightly, tests + "#, + ) + .file("build.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.a] + rustc-cfg = ["foo"] + "#, + rustc_host() + ), + ) + .file( + "src/lib.rs", + r#" + /// + /// ``` + /// extern crate foo; + /// + /// fn main() { + /// foo::foo() + /// } + /// ``` + /// + #[cfg(foo)] + pub fn foo() {} + + #[cfg(foo)] + #[test] + fn test_foo() { + foo() + } + "#, + ) + .file("tests/test.rs", "#[cfg(foo)] #[test] fn test_bar() {}") + .build(); + p.cargo("test -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo[..]` +[RUNNING] `rustc --crate-name foo[..]` +[RUNNING] `rustc --crate-name test[..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/debug/deps/test-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc [..] --cfg foo[..]` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test_foo ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test_bar ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test src/lib.rs - foo (line 3) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_override_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + links = "a" + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{target}.a] + rustc-cfg = ["foo"] + [target.{target}.b] + rustc-cfg = ["bar"] + "#, + target = rustc_host() + ), + ) + .file("build.rs", "") + .file("src/lib.rs", "#[cfg(foo)] pub fn foo() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + links = "b" + "#, + ) + .file("bar/build.rs", "") + .file("bar/src/lib.rs", "#[cfg(bar)] pub fn bar() {}") + .build(); + p.cargo("doc").run(); + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/fn.foo.html").is_file()); + assert!(p.root().join("target/doc/bar/fn.bar.html").is_file()); +} + +#[cargo_test] +fn env_build() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "src/main.rs", + r#" + const FOO: &'static str = env!("FOO"); + fn main() { + println!("{}", FOO); + } + "#, + ) + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-env=FOO=foo"); }"#, + ) + .build(); + p.cargo("build -v").run(); + p.cargo("run -v") + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); +} + +#[cargo_test] +fn env_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-env=FOO=foo"); }"#, + ) + .file( + "src/lib.rs", + r#"pub const FOO: &'static str = env!("FOO"); "#, + ) + .file( + "tests/test.rs", + r#" + extern crate foo; + + #[test] + fn test_foo() { + assert_eq!("foo", foo::FOO); + } + "#, + ) + .build(); + p.cargo("test -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build[..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo[..]` +[RUNNING] `rustc --crate-name foo[..]` +[RUNNING] `rustc --crate-name test[..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/debug/deps/test-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc --edition=2015 --crate-type lib --color auto --crate-name foo[..]` + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test_foo ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn env_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "src/main.rs", + r#" + const FOO: &'static str = env!("FOO"); + fn main() {} + "#, + ) + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-env=FOO=foo"); }"#, + ) + .build(); + p.cargo("doc -v").run(); +} + +#[cargo_test] +fn flags_go_into_tests() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + b = { path = "b" } + "#, + ) + .file("src/lib.rs", "") + .file("tests/foo.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + a = { path = "../a" } + "#, + ) + .file("b/src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + r#" + fn main() { + let path = std::env::current_dir().unwrap().parent().unwrap().join("link-dir"); + println!("cargo::rustc-link-search={}", path.display()); + } + "#, + ) + .build(); + p.root().join("link-dir").mkdir_p(); + + p.cargo("test -v --test=foo") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] a v0.5.0 ([ROOT]/foo/a) +[RUNNING] `rustc [..] a/build.rs [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/a-[HASH]/build-script-build` +[RUNNING] `rustc [..] a/src/lib.rs [..] -L [ROOT]/foo/link-dir` +[COMPILING] b v0.5.0 ([ROOT]/foo/b) +[RUNNING] `rustc [..] b/src/lib.rs [..] -L [ROOT]/foo/link-dir` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/lib.rs [..] -L [ROOT]/foo/link-dir` +[RUNNING] `rustc [..] tests/foo.rs [..] -L [ROOT]/foo/link-dir` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("test -v -pb --lib") + .with_stderr_data(str![[r#" +[FRESH] a v0.5.0 ([ROOT]/foo/a) +[COMPILING] b v0.5.0 ([ROOT]/foo/b) +[RUNNING] `rustc --crate-name b [..] -L [ROOT]/foo/link-dir` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/b-[HASH][EXE]` + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn diamond_passes_args_only_once() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + b = { path = "b" } + "#, + ) + .file("src/lib.rs", "") + .file("tests/foo.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + b = { path = "../b" } + c = { path = "../c" } + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + c = { path = "../c" } + "#, + ) + .file("b/src/lib.rs", "") + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "c/build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=native=test"); + } + "#, + ) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[LOCKING] 3 packages to latest compatible versions +[COMPILING] c v0.5.0 ([ROOT]/foo/c) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/c-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name c [..] -L native=test` +[COMPILING] b v0.5.0 ([ROOT]/foo/b) +[RUNNING] `rustc --crate-name b [..] -L native=test` +[COMPILING] a v0.5.0 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name a [..] -L native=test` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -L native=test` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn adding_an_override_invalidates() { + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file(".cargo/config.toml", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=native=foo"); + } + "#, + ) + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] -L native=foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + ".cargo/config.toml", + &format!( + " + [target.{}.foo] + rustc-link-search = [\"native=bar\"] + ", + target + ), + ); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -L native=bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_an_override_invalidates() { + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + " + [target.{}.foo] + rustc-link-search = [\"native=foo\"] + ", + target + ), + ) + .file("build.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -L native=foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + ".cargo/config.toml", + &format!( + " + [target.{}.foo] + rustc-link-search = [\"native=bar\"] + ", + target + ), + ); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -L native=bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fresh_builds_possible_with_link_libs() { + // The bug is non-deterministic. Sometimes you can get a fresh build + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "nativefoo" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + " + [target.{}.nativefoo] + rustc-link-lib = [\"a\"] + rustc-link-search = [\"./b\"] + rustc-flags = \"-l z -L ./\" + ", + target + ), + ) + .file("build.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fresh_builds_possible_with_multiple_metadata_overrides() { + // The bug is non-deterministic. Sometimes you can get a fresh build + let target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + " + [target.{}.foo] + a = \"\" + b = \"\" + c = \"\" + d = \"\" + e = \"\" + ", + target + ), + ) + .file("build.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn generate_good_d_files() { + // this is here to stop regression on an issue where build.rs rerun-if-changed paths aren't + // made absolute properly, which in turn interacts poorly with the dep-info-basedir setting, + // and the dep-info files have other-crate-relative paths spat out in them + let p = project() + .file( + "awoo/Cargo.toml", + r#" + [package] + name = "awoo" + version = "0.5.0" + edition = "2015" + build = "build.rs" + "#, + ) + .file("awoo/src/lib.rs", "") + .file( + "awoo/build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + println!("cargo::rerun-if-changed=barkbarkbark"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "meow" + version = "0.5.0" + edition = "2015" + [dependencies] + awoo = { path = "awoo" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v").run(); + + let dot_d_path = p.bin("meow").with_extension("d"); + println!("*meow at* {:?}", dot_d_path); + let dot_d = fs::read_to_string(&dot_d_path).unwrap(); + + println!("*.d file content*: {}", &dot_d); + + assert_e2e().eq( + &dot_d, + str![[r#" +[ROOT]/foo/target/debug/meow[EXE]: [ROOT]/foo/awoo/barkbarkbark [ROOT]/foo/awoo/build.rs [ROOT]/foo/awoo/src/lib.rs [ROOT]/foo/src/main.rs + +"#]], + ); + + // paths relative to dependency roots should not be allowed + assert!(!dot_d + .split_whitespace() + .any(|v| v == "barkbarkbark" || v == "build.rs")); + + p.change_file( + ".cargo/config.toml", + r#" + [build] + dep-info-basedir="." + "#, + ); + p.cargo("build -v").run(); + + let dot_d = fs::read_to_string(&dot_d_path).unwrap(); + + println!("*.d file content with dep-info-basedir*: {}", &dot_d); + + assert_e2e().eq( + &dot_d, + str![[r#" +target/debug/meow[EXE]: awoo/barkbarkbark awoo/build.rs awoo/src/lib.rs src/main.rs + +"#]], + ); + + // paths relative to dependency roots should not be allowed + assert!(!dot_d + .split_whitespace() + .any(|v| v == "barkbarkbark" || v == "build.rs")); +} + +#[cargo_test] +fn generate_good_d_files_for_external_tools() { + // This tests having a relative paths going out of the + // project root in config's dep-info-basedir + let p = project_in("rust_things") + .file( + "awoo/Cargo.toml", + r#" + [package] + name = "awoo" + version = "0.5.0" + edition = "2015" + build = "build.rs" + "#, + ) + .file("awoo/src/lib.rs", "") + .file( + "awoo/build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + println!("cargo::rerun-if-changed=barkbarkbark"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "meow" + version = "0.5.0" + edition = "2015" + [dependencies] + awoo = { path = "awoo" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [build] + dep-info-basedir="../.." + "#, + ) + .build(); + + p.cargo("build -v").run(); + + let dot_d_path = p.bin("meow").with_extension("d"); + let dot_d = fs::read_to_string(&dot_d_path).unwrap(); + + println!("*.d file content with dep-info-basedir*: {}", &dot_d); + + assert_e2e().eq(&dot_d, str![[r#" +rust_things/foo/target/debug/meow[EXE]: rust_things/foo/awoo/barkbarkbark rust_things/foo/awoo/build.rs rust_things/foo/awoo/src/lib.rs rust_things/foo/src/main.rs + +"#]]); +} + +#[cargo_test] +fn rebuild_only_on_explicit_paths() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=foo"); + println!("cargo::rerun-if-changed=bar"); + } + "#, + ) + .build(); + + p.cargo("build -v").run(); + + // files don't exist, so should always rerun if they don't exist + println!("run without"); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `foo` is missing +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + sleep_ms(1000); + p.change_file("foo", ""); + p.change_file("bar", ""); + sleep_ms(1000); // make sure the to-be-created outfile has a timestamp distinct from the infiles + + // now the exist, so run once, catch the mtime, then shouldn't run again + println!("run with"); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `foo` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + println!("run with2"); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + sleep_ms(1000); + + // random other files do not affect freshness + println!("run baz"); + p.change_file("baz", "// modified"); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // but changing dependent files does + println!("run foo change"); + p.change_file("foo", "// modified"); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `foo` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // .. as does deleting a file + println!("run bar delete"); + fs::remove_file(p.root().join("bar")).unwrap(); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the file `bar` is missing +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn doctest_receives_build_link_args() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "bar" + build = "build.rs" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=native=bar"); + } + "#, + ) + .build(); + + p.cargo("test -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--crate-name foo --test [..]-L native=bar[..]` + +"#]]) + .run(); +} + +#[cargo_test] +fn please_respect_the_dag() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies] + a = { path = 'a' } + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=native=foo"); + } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "bar" + build = "build.rs" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=native=bar"); + } + "#, + ) + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustc --crate-name foo [..] -L native=foo -L native=bar` +... +"#]]) + .run(); +} + +#[cargo_test] +fn non_utf8_output() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#" + use std::io::prelude::*; + + fn main() { + let mut out = std::io::stdout(); + // print something that's not utf8 + out.write_all(b"\xff\xff\n").unwrap(); + + // now print some cargo metadata that's utf8 + println!("cargo::rustc-cfg=foo"); + + // now print more non-utf8 + out.write_all(b"\xff\xff\n").unwrap(); + } + "#, + ) + .file("src/main.rs", "#[cfg(foo)] fn main() {}") + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn custom_target_dir() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = 'test' + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("a/build.rs", "fn main() {}") + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn panic_abort_with_build_scripts() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [profile.release] + panic = 'abort' + + [dependencies] + a = { path = "a" } + "#, + ) + .file( + "src/lib.rs", + "#[allow(unused_extern_crates)] extern crate a;", + ) + .file("build.rs", "fn main() {}") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [build-dependencies] + b = { path = "../b" } + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + "#[allow(unused_extern_crates)] extern crate b; fn main() {}", + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build -v --release").run(); + + p.root().join("target").rm_rf(); + + p.cargo("test --release -v") + .with_stderr_does_not_contain("[..]panic=abort[..]") + .run(); +} + +#[cargo_test] +fn warnings_emitted() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[WARNING] foo@0.5.0: foo +[WARNING] foo@0.5.0: bar +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn errors_and_warnings_emitted_and_build_failed() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + println!("cargo::error=foo err"); + println!("cargo::error=bar err"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[WARNING] foo@0.5.0: foo +[WARNING] foo@0.5.0: bar +[ERROR] foo@0.5.0: foo err +[ERROR] foo@0.5.0: bar err +[ERROR] build script logged errors + +"#]]) + .run(); +} + +#[cargo_test] +fn warnings_emitted_from_path_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] a v0.5.0 ([ROOT]/foo/a) +[WARNING] a@0.5.0: foo +[WARNING] a@0.5.0: bar +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn warnings_emitted_when_build_script_panics() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + panic!("our crate panicked"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[WARNING] foo@0.5.0: foo +[WARNING] foo@0.5.0: bar +[ERROR] failed to run custom build command for `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` ([EXIT_STATUS]: 101) + --- stdout + cargo::warning=foo + cargo::warning=bar + + --- stderr +... +[..]our crate panicked[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn warnings_emitted_when_dependency_panics() { + Package::new("published", "0.1.0") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + panic!("dependency panicked"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "published" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + published = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] published v0.1.0 (registry `dummy-registry`) +[COMPILING] published v0.1.0 +[WARNING] published@0.1.0: foo +[WARNING] published@0.1.0: bar +[ERROR] failed to run custom build command for `published v0.1.0` + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/build/published-[HASH]/build-script-build` ([EXIT_STATUS]: 101) + --- stdout + cargo::warning=foo + cargo::warning=bar + + --- stderr +... +[..]dependency panicked[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn log_messages_emitted_when_dependency_logs_errors() { + Package::new("published", "0.1.0") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + println!("cargo::error=foo err"); + println!("cargo::error=bar err"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "published" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + published = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] published v0.1.0 (registry `dummy-registry`) +[COMPILING] published v0.1.0 +[WARNING] published@0.1.0: foo +[WARNING] published@0.1.0: bar +[ERROR] published@0.1.0: foo err +[ERROR] published@0.1.0: bar err +[ERROR] build script logged errors + +"#]]) + .run(); +} + +#[cargo_test] +fn warnings_hidden_for_upstream() { + Package::new("bar", "0.1.0") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[COMPILING] bar v0.1.0 +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name bar [..]` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn warnings_printed_on_vv() { + Package::new("bar", "0.1.0") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::warning=foo"); + println!("cargo::warning=bar"); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -vv") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[COMPILING] bar v0.1.0 +[RUNNING] `[..] rustc --crate-name build_script_build [..]` +[RUNNING] `[..] [ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build` +[WARNING] bar@0.1.0: foo +[WARNING] bar@0.1.0: bar +[RUNNING] `[..] rustc --crate-name bar [..]` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn output_shows_on_vv() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::io::prelude::*; + + fn main() { + std::io::stderr().write_all(b"stderr\n").unwrap(); + std::io::stdout().write_all(b"stdout\n").unwrap(); + } + "#, + ) + .build(); + + p.cargo("build -vv") + .with_stdout_data(str![[r#" +[foo 0.5.0] stdout + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build [..]` +[RUNNING] `[..] [ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[foo 0.5.0] stderr +[RUNNING] `[..] rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn links_with_dots() { + let target = rustc_host(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + links = "a.b" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-search=bar") + } + "#, + ) + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.'a.b'] + rustc-link-search = ["foo"] + "#, + target + ), + ) + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -L foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_and_rustdoc_set_correctly() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + + fn main() { + assert_eq!(env::var("RUSTC").unwrap(), "rustc"); + assert_eq!(env::var("RUSTDOC").unwrap(), "rustdoc"); + } + "#, + ) + .build(); + p.cargo("bench").run(); +} + +#[cargo_test] +fn cfg_env_vars_available() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + + fn main() { + let fam = env::var("CARGO_CFG_TARGET_FAMILY").unwrap(); + if cfg!(unix) { + assert_eq!(fam, "unix"); + } else { + assert_eq!(fam, "windows"); + } + } + "#, + ) + .build(); + p.cargo("bench").run(); +} + +#[cargo_test] +fn switch_features_rerun() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + + [features] + foo = [] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!(include_str!(concat!(env!("OUT_DIR"), "/output"))); + } + "#, + ) + .file( + "build.rs", + r#" + use std::env; + use std::fs; + use std::path::Path; + + fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let output = Path::new(&out_dir).join("output"); + + if env::var_os("CARGO_FEATURE_FOO").is_some() { + fs::write(output, "foo").unwrap(); + } else { + fs::write(output, "bar").unwrap(); + } + } + "#, + ) + .build(); + + p.cargo("build -v --features=foo").run(); + p.rename_run("foo", "with_foo") + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); + p.cargo("build -v").run(); + p.rename_run("foo", "without_foo") + .with_stdout_data(str![[r#" +bar + +"#]]) + .run(); + p.cargo("build -v --features=foo").run(); + p.rename_run("foo", "with_foo2") + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); +} + +#[cargo_test] +fn assume_build_script_when_build_rs_present() { + let p = project() + .file( + "src/main.rs", + r#" + fn main() { + if ! cfg!(foo) { + panic!("the build script was not run"); + } + } + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-cfg=foo"); + } + "#, + ) + .build(); + + p.cargo("run -v").run(); +} + +#[cargo_test] +fn if_build_set_to_false_dont_treat_build_rs_as_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = false + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(foo) { + panic!("the build script was run"); + } + } + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-cfg=foo"); + } + "#, + ) + .build(); + + p.cargo("run -v").run(); +} + +#[cargo_test] +fn deterministic_rustc_dependency_flags() { + // This bug is non-deterministic hence the large number of dependencies + // in the hopes it will have a much higher chance of triggering it. + + Package::new("dep1", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "dep1" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-flags=-L native=test1"); + } + "#, + ) + .file("src/lib.rs", "") + .publish(); + Package::new("dep2", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "dep2" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-flags=-L native=test2"); + } + "#, + ) + .file("src/lib.rs", "") + .publish(); + Package::new("dep3", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "dep3" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-flags=-L native=test3"); + } + "#, + ) + .file("src/lib.rs", "") + .publish(); + Package::new("dep4", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "dep4" + version = "0.1.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-flags=-L native=test4"); + } + "#, + ) + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = "*" + dep2 = "*" + dep3 = "*" + dep4 = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v").with_stderr_data(str![[r#" +... +[RUNNING] `rustc --crate-name foo [..] -L native=test1 -L native=test2 -L native=test3 -L native=test4` +... +"#]]).run(); +} + +#[cargo_test] +fn links_duplicates_with_cycle() { + // this tests that the links_duplicates are caught at resolver time + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + + [dependencies.a] + path = "a" + + [dev-dependencies] + b = { path = "b" } + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + "#, + ) + .file("a/src/lib.rs", "") + .file("a/build.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = ".." } + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to select a version for `a`. + ... required by package `foo v0.5.0 ([ROOT]/foo)` +versions that meet the requirements `*` are: 0.5.0 + +the package `a` links to the native library `a`, but it conflicts with a previous package which links to `a` as well: +package `foo v0.5.0 ([ROOT]/foo)` +Only one package in the dependency graph may specify the same links value. This helps ensure that only one copy of a native library is linked in the final binary. Try to adjust your dependencies so that only one package uses the `links = "a"` value. For more information, see https://doc.rust-lang.org/cargo/reference/resolver.html#links. + +failed to select a version for `a` which could resolve this conflict + +"#]]) + .run(); +} + +#[cargo_test] +fn rename_with_link_search_path() { + _rename_with_link_search_path( + false, + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/bar[EXE]` + +"#]], + ); +} + +#[cargo_test] +#[cfg_attr( + target_os = "macos", + ignore = "don't have a cdylib cross target on macos" +)] +fn rename_with_link_search_path_cross() { + if cross_compile::disabled() { + return; + } + + _rename_with_link_search_path( + true, + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/[ALT_TARGET]/debug/bar[EXE]` + +"#]], + ); +} + +fn _rename_with_link_search_path(cross: bool, expected: impl IntoData) { + let target_arg = if cross { + format!(" --target={}", cross_compile::alternate()) + } else { + "".to_string() + }; + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [lib] + crate-type = ["cdylib"] + "#, + ) + .file( + "src/lib.rs", + r#"#[no_mangle] pub extern "C" fn cargo_test_foo() {}"#, + ); + let p = p.build(); + + p.cargo(&format!("build{}", target_arg)).run(); + + let p2 = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file( + "build.rs", + r#" + use std::env; + use std::fs; + use std::path::PathBuf; + + fn main() { + // Move the `libfoo.so` from the root of our project into the + // build directory. This way Cargo should automatically manage + // `LD_LIBRARY_PATH` and such. + let root = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); + let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX); + let src = root.join(&file); + + let dst_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let dst = dst_dir.join(&file); + + fs::copy(&src, &dst).unwrap(); + // handle windows, like below + drop(fs::copy(root.join("foo.dll.lib"), dst_dir.join("foo.dll.lib"))); + + println!("cargo::rerun-if-changed=build.rs"); + if cfg!(target_env = "msvc") { + println!("cargo::rustc-link-lib=foo.dll"); + } else { + println!("cargo::rustc-link-lib=foo"); + } + println!("cargo::rustc-link-search=all={}", + dst.parent().unwrap().display()); + } + "#, + ) + .file( + "src/main.rs", + r#" + extern "C" { + #[link_name = "cargo_test_foo"] + fn foo(); + } + + fn main() { + unsafe { foo(); } + } + "#, + ); + let p2 = p2.build(); + + // Move the output `libfoo.so` into the directory of `p2`, and then delete + // the `p` project. On macOS, the `libfoo.dylib` artifact references the + // original path in `p` so we want to make sure that it can't find it (hence + // the deletion). + let root = if cross { + p.root() + .join("target") + .join(cross_compile::alternate()) + .join("debug") + .join("deps") + } else { + p.root().join("target").join("debug").join("deps") + }; + let file = format!("{}foo{}", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX); + let src = root.join(&file); + + let dst = p2.root().join(&file); + + fs::copy(&src, &dst).unwrap(); + // copy the import library for windows, if it exists + drop(fs::copy( + &root.join("foo.dll.lib"), + p2.root().join("foo.dll.lib"), + )); + remove_dir_all(p.root()).unwrap(); + + // Everything should work the first time + p2.cargo(&format!("run{}", target_arg)).run(); + + // Now rename the root directory and rerun `cargo run`. Not only should we + // not build anything but we also shouldn't crash. + let mut new = p2.root(); + new.pop(); + new.push("bar2"); + + // For whatever reason on Windows right after we execute a binary it's very + // unlikely that we're able to successfully delete or rename that binary. + // It's not really clear why this is the case or if it's a bug in Cargo + // holding a handle open too long. In an effort to reduce the flakiness of + // this test though we throw this in a loop + // + // For some more information see #5481 and rust-lang/rust#48775 + let mut i = 0; + loop { + let error = match fs::rename(p2.root(), &new) { + Ok(()) => break, + Err(e) => e, + }; + i += 1; + if !cfg!(windows) || error.kind() != io::ErrorKind::PermissionDenied || i > 10 { + panic!("failed to rename: {}", error); + } + println!("assuming {} is spurious, waiting to try again", error); + thread::sleep(slow_cpu_multiplier(100)); + } + + p2.cargo(&format!("run{}", target_arg)) + .cwd(&new) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn optional_build_script_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar", optional = true } + + [build-dependencies] + bar = { path = "bar", optional = true } + "#, + ) + .file( + "build.rs", + r#" + #[cfg(feature = "bar")] + extern crate bar; + + fn main() { + #[cfg(feature = "bar")] { + println!("cargo::rustc-env=FOO={}", bar::bar()); + return + } + println!("cargo::rustc-env=FOO=0"); + } + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(feature = "bar")] + extern crate bar; + + fn main() { + println!("{}", env!("FOO")); + } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("bar/src/lib.rs", "pub fn bar() -> u32 { 1 }"); + let p = p.build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +0 + +"#]]) + .run(); + p.cargo("run --features bar") + .with_stdout_data(str![[r#" +1 + +"#]]) + .run(); +} + +#[cargo_test] +fn optional_build_dep_and_required_normal_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "./bar", optional = true } + + [build-dependencies] + bar = { path = "./bar" } + "#, + ) + .file("build.rs", "extern crate bar; fn main() { bar::bar(); }") + .file( + "src/main.rs", + r#" + #[cfg(feature = "bar")] + extern crate bar; + + fn main() { + #[cfg(feature = "bar")] { + println!("{}", bar::bar()); + } + #[cfg(not(feature = "bar"))] { + println!("0"); + } + } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("bar/src/lib.rs", "pub fn bar() -> u32 { 1 }"); + let p = p.build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +0 + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + + p.cargo("run --all-features") + .with_stdout_data(str![[r#" +1 + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn using_rerun_if_changed_does_not_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn links_interrupted_can_restart() { + // Test for a `links` dependent build script getting canceled and then + // restarted. Steps: + // 1. Build to establish fingerprints. + // 2. Change something (an env var in this case) that triggers the + // dependent build script to run again. Kill the top-level build script + // while it is running (such as hitting Ctrl-C). + // 3. Run the build again, it should re-run the build script. + let bar = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + links = "foo" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=SOMEVAR"); + } + "#, + ) + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.bar] + path = '{}' + "#, + bar.root().display() + ), + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + fn main() { + println!("cargo::metadata=rebuild-if-changed=build.rs"); + if std::path::Path::new("abort").exists() { + panic!("Crash!"); + } + } + "#, + ) + .build(); + + p.cargo("build").run(); + // Simulate the user hitting Ctrl-C during a build. + p.change_file("abort", ""); + // Set SOMEVAR to trigger a rebuild. + p.cargo("build") + .env("SOMEVAR", "1") + .with_stderr_data(str![[r#" +... + Crash! +... +"#]]) + .with_status(101) + .run(); + fs::remove_file(p.root().join("abort")).unwrap(); + // Try again without aborting the script. + // ***This is currently broken, the script does not re-run. + p.cargo("build -v") + .env("SOMEVAR", "1") + .with_stderr_data(str![[r#" +... +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +... +"#]]) + .run(); +} + +#[cargo_test] +fn dev_dep_with_links() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + links = "x" + + [dev-dependencies] + bar = { path = "./bar" } + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + links = "y" + + [dependencies] + foo = { path = ".." } + "#, + ) + .file("bar/build.rs", "fn main() {}") + .file("bar/src/lib.rs", "") + .build(); + p.cargo("check --tests").run(); +} + +#[cargo_test] +fn rerun_if_directory() { + if !symlink_supported() { + return; + } + + // rerun-if-changed of a directory should rerun if any file in the directory changes. + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=somedir"); + } + "#, + ) + .build(); + + let dirty = |expected| { + p.cargo("check -v").with_stderr_data(expected).run(); + }; + + let fresh = || { + p.cargo("check") + .with_stderr_data( + "\ +[FINISHED] [..] +", + ) + .run(); + }; + + // Start with a missing directory. + dirty(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build[..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + // Because the directory doesn't exist, it will trigger a rebuild every time. + // https://github.com/rust-lang/cargo/issues/6003 + dirty(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` is missing +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + + if is_coarse_mtime() { + sleep_ms(1000); + } + + // Empty directory. + fs::create_dir(p.root().join("somedir")).unwrap(); + dirty(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + fresh(); + + if is_coarse_mtime() { + sleep_ms(1000); + } + + // Add a file. + p.change_file("somedir/foo", ""); + p.change_file("somedir/bar", ""); + dirty(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + fresh(); + + if is_coarse_mtime() { + sleep_ms(1000); + } + + // Add a symlink. + p.symlink("foo", "somedir/link"); + dirty(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + fresh(); + + if is_coarse_mtime() { + sleep_ms(1000); + } + + // Move the symlink. + fs::remove_file(p.root().join("somedir/link")).unwrap(); + p.symlink("bar", "somedir/link"); + dirty(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + fresh(); + + if is_coarse_mtime() { + sleep_ms(1000); + } + + // Remove a file. + fs::remove_file(p.root().join("somedir/foo")).unwrap(); + dirty(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the file `somedir` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + fresh(); +} + +#[cargo_test] +fn rerun_if_published_directory() { + // build script of a dependency contains a `rerun-if-changed` pointing to a directory + Package::new("mylib-sys", "1.0.0") + .file("mylib/balrog.c", "") + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + // Changing to mylib/balrog.c will not trigger a rebuild + println!("cargo::rerun-if-changed=mylib"); + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + mylib-sys = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); + + // Delete regitry src to make directories being recreated with the latest timestamp. + cargo_home().join("registry/src").rm_rf(); + + p.cargo("check --verbose") + .with_stderr_data(str![[r#" +[FRESH] mylib-sys v1.0.0 +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Upgrade of a package should still trigger a rebuild + Package::new("mylib-sys", "1.0.1") + .file("mylib/balrog.c", "") + .file("mylib/balrog.h", "") + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=mylib"); + } + "#, + ) + .publish(); + p.cargo("update").run(); + p.cargo("fetch").run(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[COMPILING] mylib-sys v1.0.1 +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/mylib-sys-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name mylib_sys [..]` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn test_with_dep_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + assert_eq!(std::env::var("DEP_BAR_FOO").unwrap(), "bar"); + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + links = 'bar' + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "bar/build.rs", + r#" + fn main() { + println!("cargo::metadata=foo=bar"); + } + "#, + ) + .build(); + p.cargo("test --lib").run(); +} + +#[cargo_test] +fn duplicate_script_with_extra_env() { + // Test where a build script is run twice, that emits different rustc-env + // and rustc-cfg values. In this case, one is run for host, the other for + // target. + if !cross_compile::can_run_on_host() { + return; + } + + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "pm"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + pm = { path = "../pm" } + "#, + ) + .file( + "foo/src/lib.rs", + &r#" + //! ```rust + //! #[cfg(not(mycfg="{target}"))] + //! compile_error!{"expected mycfg set"} + //! assert_eq!(env!("CRATE_TARGET"), "{target}"); + //! assert_eq!(std::env::var("CRATE_TARGET").unwrap(), "{target}"); + //! ``` + + #[test] + fn check_target() { + #[cfg(not(mycfg="{target}"))] + compile_error!{"expected mycfg set"} + // Compile-time assertion. + assert_eq!(env!("CRATE_TARGET"), "{target}"); + // Run-time assertion. + assert_eq!(std::env::var("CRATE_TARGET").unwrap(), "{target}"); + } + "# + .replace("{target}", target), + ) + .file( + "foo/build.rs", + r#" + fn main() { + println!("cargo::rustc-env=CRATE_TARGET={}", std::env::var("TARGET").unwrap()); + println!("cargo::rustc-cfg=mycfg=\"{}\"", std::env::var("TARGET").unwrap()); + } + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + + [lib] + proc-macro = true + # This is just here to speed things up. + doctest = false + + [dev-dependencies] + foo = { path = "../foo" } + "#, + ) + .file("pm/src/lib.rs", "") + .build(); + + p.cargo("test --workspace --target") + .arg(&target) + .with_stdout_data(str![[r#" +... +test check_target ... ok +... +"#]]) + .run(); + + if cargo_test_support::is_nightly() { + p.cargo("test --workspace -Z doctest-xcompile --doc --target") + .arg(&target) + .masquerade_as_nightly_cargo(&["doctest-xcompile"]) + .with_stdout_data(str![[r#" +... +test foo/src/lib.rs - (line 2) ... ok +... +"#]]) + .run(); + } +} + +#[cargo_test] +fn wrong_output() { + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::example"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo::example` +Expected a line with `cargo::KEY=VALUE` with an `=` character, but none was found. +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs. + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_build_closes_stdin() { + // Ensure stdin is closed to prevent deadlock. + // See https://github.com/rust-lang/cargo/issues/11196 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#"fn main() { + let mut line = String::new(); + std::io::stdin().read_line(&mut line).unwrap(); + }"#, + ) + .build(); + p.cargo("build").run(); +} + +#[cargo_test] +fn test_old_syntax() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "src/main.rs", + r#" + const FOO: &'static str = env!("FOO"); + fn main() { + println!("{}", FOO); + } + "#, + ) + .file( + "build.rs", + r#"fn main() { + println!("cargo:rustc-env=FOO=foo"); + println!("cargo:foo=foo"); + }"#, + ) + .build(); + p.cargo("build -v").run(); + p.cargo("run -v") + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); +} + +#[cargo_test] +fn test_invalid_old_syntax() { + // Unexpected metadata value. + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo:foo"); + } + "#, + ) + .build(); + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo:foo` +Expected a line with `cargo:KEY=VALUE` with an `=` character, but none was found. +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs. + +"#]]) + .run(); +} + +#[cargo_test] +fn test_invalid_new_syntax() { + // Unexpected metadata value. + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::metadata=foo"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo::metadata=foo` +Expected a line with `cargo::metadata=KEY=VALUE` with an `=` character, but none was found. +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs. + +"#]]) + .run(); + // `cargo::` can not be used with the unknown key. + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::foo=bar"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] invalid output in build script of `foo v0.0.1 ([ROOT]/foo)`: `cargo::foo=bar` +Unknown key: `foo`. +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs. + +"#]]) + .run(); +} + +#[cargo_test] +fn test_new_syntax_with_old_msrv() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + rust-version = "1.60.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::metadata=foo=bar"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[ERROR] the `cargo::` syntax for build script output instructions was added in Rust 1.77.0, but the minimum supported Rust version of `foo v0.5.0 ([ROOT]/foo)` is 1.60.0. +Switch to the old `cargo:foo=bar` syntax instead of `cargo::metadata=foo=bar` (note the single colon). +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs. + +"#]]) + .run(); +} + +#[cargo_test] +fn test_new_syntax_with_old_msrv_and_reserved_prefix() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + rust-version = "1.60.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-check-cfg=cfg(foo)"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[ERROR] the `cargo::` syntax for build script output instructions was added in Rust 1.77.0, but the minimum supported Rust version of `foo v0.5.0 ([ROOT]/foo)` is 1.60.0. +Switch to the old `cargo:rustc-check-cfg=cfg(foo)` syntax (note the single colon). +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs. + +"#]]) + .run(); +} + +#[cargo_test] +fn test_new_syntax_with_old_msrv_and_unknown_prefix() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + rust-version = "1.60.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::foo=bar"); + } + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[ERROR] the `cargo::` syntax for build script output instructions was added in Rust 1.77.0, but the minimum supported Rust version of `foo v0.5.0 ([ROOT]/foo)` is 1.60.0. +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script for more information about build script outputs. + +"#]]) + .run(); +} + +#[cargo_test] +fn test_new_syntax_with_compatible_partial_msrv() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2015" + build = "build.rs" + rust-version = "1.77" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::metadata=foo=bar"); + } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn test_old_syntax_with_old_msrv() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + rust-version = "1.60.0" + "#, + ) + .file( + "src/main.rs", + r#" + const FOO: &'static str = env!("FOO"); + fn main() { + println!("{}", FOO); + } + "#, + ) + .file( + "build.rs", + r#"fn main() { + println!("cargo:rustc-env=FOO=foo"); + println!("cargo:foo=foo"); + }"#, + ) + .build(); + p.cargo("build -v").run(); + p.cargo("run -v") + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); +} + +#[cargo_test] +fn build_script_rerun_when_target_rustflags_change() { + let target = rustc_host(); + let p = project() + .file( + "src/main.rs", + r#" + fn main() { + #[cfg(enable)] + println!("hello"); + } + "#, + ) + .file( + "build.rs", + r#" + use std::env; + + fn main() { + println!("cargo::rustc-check-cfg=cfg(enable)"); + if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") { + if !rustflags.is_empty() { + println!("cargo::rustc-cfg=enable"); + } + } + } + "#, + ) + .build(); + + p.cargo("run --target") + .arg(&target) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/[HOST_TARGET]/debug/foo[EXE]` + +"#]]) + .run(); + + p.cargo("run --target") + .arg(&target) + .env("RUSTFLAGS", "-C opt-level=3") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/[HOST_TARGET]/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn links_overrides_with_target_applies_to_host() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "mylib-sys" + edition = "2021" + version = "0.0.1" + authors = [] + links = "mylib" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "bad file") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .args(&[ + "-Ztarget-applies-to-host", + "--config", + "target-applies-to-host=false", + ]) + .args(&[ + "--config", + &format!(r#"target.{}.mylib.rustc-link-search=["foo"]"#, rustc_host()), + ]) + .with_stderr_data(str![[r#" +[COMPILING] mylib-sys v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name mylib_sys [..] -L foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn directory_with_leading_underscore() { + let p: cargo_test_support::Project = git::new("foo", |p| { + p.no_manifest() + .file( + "_foo/foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + build = "build.rs" + "#, + ) + .file("_foo/foo/src/main.rs", "fn main() {}") + .file("_foo/foo/build.rs", "fn main() { }") + }); + p.cargo("build --manifest-path=_foo/foo/Cargo.toml -v") + .with_status(0) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_env.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_env.rs new file mode 100644 index 000000000..db48bcd83 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_env.rs @@ -0,0 +1,454 @@ +//! Tests for build.rs rerun-if-env-changed and rustc-env + +use cargo_test_support::basic_manifest; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::sleep_ms; +use cargo_test_support::str; + +#[cargo_test] +fn rerun_if_env_changes() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=FOO"); + } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .env("FOO", "baz") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .env("FOO", "baz") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rerun_if_env_or_file_changes() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=FOO"); + println!("cargo::rerun-if-changed=foo"); + } + "#, + ) + .file("foo", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + sleep_ms(1000); + p.change_file("foo", "// modified"); + p.cargo("check") + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_bootstrap() { + let build_rs = r#" + fn main() { + println!("cargo::rustc-env=RUSTC_BOOTSTRAP=1"); + } + "#; + let p = project() + .file("Cargo.toml", &basic_manifest("has-dashes", "0.0.1")) + .file( + "src/lib.rs", + "#![allow(internal_features)] #![feature(rustc_attrs)]", + ) + .file("build.rs", build_rs) + .build(); + // RUSTC_BOOTSTRAP unset on stable should error + p.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] has-dashes v0.0.1 ([ROOT]/foo) +[ERROR] Cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`. +[NOTE] Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project. +[HELP] If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP=has_dashes` before running cargo instead. + +"#]]) + .with_status(101) + .run(); + // nightly should warn whether or not RUSTC_BOOTSTRAP is set + p.cargo("check") + .masquerade_as_nightly_cargo(&["RUSTC_BOOTSTRAP"]) + // NOTE: uses RUSTC_BOOTSTRAP so it will be propagated to rustc + // (this matters when tests are being run with a beta or stable cargo) + .env("RUSTC_BOOTSTRAP", "1") + .with_stderr_data(str![[r#" +[COMPILING] has-dashes v0.0.1 ([ROOT]/foo) +[WARNING] has-dashes@0.0.1: Cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`. +[NOTE] Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // RUSTC_BOOTSTRAP set to the name of the library should warn + p.cargo("check") + .env("RUSTC_BOOTSTRAP", "has_dashes") + .with_stderr_data(str![[r#" +[WARNING] has-dashes@0.0.1: Cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`. +[NOTE] Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // RUSTC_BOOTSTRAP set to some random value should error + p.cargo("check") + .env("RUSTC_BOOTSTRAP", "bar") + .with_stderr_data(str![[r#" +[ERROR] Cannot set `RUSTC_BOOTSTRAP=1` from build script of `has-dashes v0.0.1 ([ROOT]/foo)`. +[NOTE] Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project. +[HELP] If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP=has_dashes` before running cargo instead. + +"#]]) + .with_status(101) + .run(); + + // Tests for binaries instead of libraries + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.0.1")) + .file( + "src/main.rs", + "#![allow(internal_features)] #![feature(rustc_attrs)] fn main() {}", + ) + .file("build.rs", build_rs) + .build(); + // nightly should warn when there's no library whether or not RUSTC_BOOTSTRAP is set + p.cargo("check") + .masquerade_as_nightly_cargo(&["RUSTC_BOOTSTRAP"]) + // NOTE: uses RUSTC_BOOTSTRAP so it will be propagated to rustc + // (this matters when tests are being run with a beta or stable cargo) + .env("RUSTC_BOOTSTRAP", "1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[WARNING] foo@0.0.1: Cannot set `RUSTC_BOOTSTRAP=1` from build script of `foo v0.0.1 ([ROOT]/foo)`. +[NOTE] Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // RUSTC_BOOTSTRAP conditionally set when there's no library should error (regardless of the value) + p.cargo("check") + .env("RUSTC_BOOTSTRAP", "foo") + .with_stderr_data(str![[r#" +[ERROR] Cannot set `RUSTC_BOOTSTRAP=1` from build script of `foo v0.0.1 ([ROOT]/foo)`. +[NOTE] Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project. +[HELP] If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP=1` before running cargo instead. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn build_script_env_verbose() { + let build_rs = r#" + fn main() {} + "#; + let p = project() + .file("Cargo.toml", &basic_manifest("verbose-build", "0.0.1")) + .file("src/lib.rs", "") + .file("build.rs", build_rs) + .build(); + + p.cargo("check -vv") + .with_stderr_data( + "\ +... +[RUNNING] `[..]CARGO=[..]build-script-build` +...", + ) + .run(); +} + +#[cargo_test] +#[cfg(target_arch = "x86_64")] +fn build_script_sees_cfg_target_feature() { + let build_rs = r#" + fn main() { + let cfg = std::env::var("CARGO_CFG_TARGET_FEATURE").unwrap(); + eprintln!("CARGO_CFG_TARGET_FEATURE={cfg}"); + } + "#; + + let configs = [ + r#" + [build] + rustflags = ["-Ctarget-feature=+sse4.1,+sse4.2"] + "#, + r#" + [target.'cfg(target_arch = "x86_64")'] + rustflags = ["-Ctarget-feature=+sse4.1,+sse4.2"] + "#, + ]; + + for config in configs { + let p = project() + .file(".cargo/config.toml", config) + .file("src/lib.rs", r#""#) + .file("build.rs", build_rs) + .build(); + + p.cargo("check -vv") + .with_stderr_data( + "\ +... +[foo 0.0.1] CARGO_CFG_TARGET_FEATURE=[..]sse4.2[..] +... +[..]-Ctarget-feature=[..]+sse4.2[..] +...", + ) + .run(); + } +} + +/// In this test, the cfg is self-contradictory. There's no *right* answer as to +/// what the value of `RUSTFLAGS` should be in this case. We chose to give a +/// warning. However, no matter what we do, it's important that build scripts +/// and rustc see a consistent picture +#[cargo_test] +fn cfg_paradox() { + let build_rs = r#" + fn main() { + let cfg = std::env::var("CARGO_CFG_BERTRAND").is_ok(); + eprintln!("cfg!(bertrand)={cfg}"); + } + "#; + + let config = r#" + [target.'cfg(not(bertrand))'] + rustflags = ["--cfg=bertrand"] + "#; + + let p = project() + .file(".cargo/config.toml", config) + .file("src/lib.rs", r#""#) + .file("build.rs", build_rs) + .build(); + + p.cargo("check -vv") + .with_stderr_data( + "\ +[WARNING] non-trivial mutual dependency between target-specific configuration and RUSTFLAGS +... +[foo 0.0.1] cfg!(bertrand)=true +... +[..]--cfg=bertrand[..] +...", + ) + .run(); +} + +/// This test checks how Cargo handles rustc cfgs which are defined both with +/// and without a value. The expected behavior is that the environment variable +/// is going to contain all the values. +/// +/// For example, this configuration: +/// ``` +/// target_has_atomic +/// target_has_atomic="16" +/// target_has_atomic="32" +/// target_has_atomic="64" +/// target_has_atomic="8" +/// target_has_atomic="ptr" +/// ``` +/// +/// Should result in the following environment variable: +/// +/// ``` +/// CARGO_CFG_TARGET_HAS_ATOMIC=16,32,64,8,ptr +/// ``` +/// +/// On the other hand, configuration symbols without any value should result in +/// an empty string. +/// +/// For example, this configuration: +/// +/// ``` +/// target_thread_local +/// ``` +/// +/// Should result in the following environment variable: +/// +/// ``` +/// CARGO_CFG_TARGET_THREAD_LOCAL= +/// ``` +#[cargo_test(nightly, reason = "affected rustc cfg is unstable")] +#[cfg(target_arch = "x86_64")] +fn rustc_cfg_with_and_without_value() { + let build_rs = r#" + fn main() { + let cfg = std::env::var("CARGO_CFG_TARGET_HAS_ATOMIC"); + eprintln!("CARGO_CFG_TARGET_HAS_ATOMIC={cfg:?}"); + let cfg = std::env::var("CARGO_CFG_WINDOWS"); + eprintln!("CARGO_CFG_WINDOWS={cfg:?}"); + let cfg = std::env::var("CARGO_CFG_UNIX"); + eprintln!("CARGO_CFG_UNIX={cfg:?}"); + } + "#; + let p = project() + .file("src/lib.rs", r#""#) + .file("build.rs", build_rs) + .build(); + + let mut check = p.cargo("check -vv"); + #[cfg(target_has_atomic = "64")] + check.with_stderr_data( + "\ +... +[foo 0.0.1] CARGO_CFG_TARGET_HAS_ATOMIC=Ok(\"[..]64[..]\") +...", + ); + #[cfg(windows)] + check.with_stderr_data( + "\ +... +[foo 0.0.1] CARGO_CFG_WINDOWS=Ok(\"\") +...", + ); + #[cfg(unix)] + check.with_stderr_data( + "\ +... +[foo 0.0.1] CARGO_CFG_UNIX=Ok(\"\") +...", + ); + check.run(); +} + +#[cargo_test] +fn rerun_if_env_is_exsited_config() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=FOO"); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + FOO = "foo" + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo(r#"check --config 'env.FOO="bar"'"#) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rerun_if_env_newly_added_in_config() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=FOO"); + } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo(r#"check --config 'env.FOO="foo"'"#) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_extra_link_arg.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_extra_link_arg.rs new file mode 100644 index 000000000..ad3a8d13b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/build_script_extra_link_arg.rs @@ -0,0 +1,405 @@ +//! Tests for additional link arguments. + +// NOTE: Many of these tests use `without_status()` when passing bogus flags +// because MSVC link.exe just gives a warning on unknown flags (how helpful!), +// and other linkers will return an error. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project}; + +#[cargo_test] +fn build_script_extra_link_arg_bin() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg-bins=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("build -v") + .without_status() + .with_stderr_data( + "\ +... +[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..] +...", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_arg_bin_single() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foobar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [[bin]] + name = "foo" + [[bin]] + name = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg-bins=--bogus-flag-all"); + println!("cargo::rustc-link-arg-bin=foo=--bogus-flag-foo"); + println!("cargo::rustc-link-arg-bin=bar=--bogus-flag-bar"); + } + "#, + ) + .build(); + + p.cargo("build -v") + .without_status() + .with_stderr_data( + "\ +... +[RUNNING] `rustc --crate-name foo [..]-C link-arg=--bogus-flag-all -C link-arg=--bogus-flag-foo[..] +...", + ) + .with_stderr_data( + "\ +... +[RUNNING] `rustc --crate-name bar [..]-C link-arg=--bogus-flag-all -C link-arg=--bogus-flag-bar[..] +...", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_arg() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("build -v") + .without_status() + .with_stderr_data( + "\ +... +[RUNNING] `rustc --crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..] +...", + ) + .run(); +} + +#[cargo_test] +fn link_arg_missing_target() { + // Errors when a given target doesn't exist. + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-link-arg-cdylib=--bogus"); }"#, + ) + .build(); + + // TODO: Uncomment this if cdylib restriction is re-added (see + // cdylib_link_arg_transitive below). + // p.cargo("check") + // .with_status(101) + // .with_stderr("\ + // [COMPILING] foo [..] + // error: invalid instruction `cargo::rustc-link-arg-cdylib` from build script of `foo v0.0.1 ([ROOT]/foo)` + // The package foo v0.0.1 ([ROOT]/foo) does not have a cdylib target. + // ") + // .run(); + + p.change_file( + "build.rs", + r#"fn main() { println!("cargo::rustc-link-arg-bins=--bogus"); }"#, + ); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] invalid instruction `cargo::rustc-link-arg-bins` from build script of `foo v0.0.1 ([ROOT]/foo)` +The package foo v0.0.1 ([ROOT]/foo) does not have a bin target. + +"#]]) + .run(); + + p.change_file( + "build.rs", + r#"fn main() { println!("cargo::rustc-link-arg-bin=abc=--bogus"); }"#, + ); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] invalid instruction `cargo::rustc-link-arg-bin` from build script of `foo v0.0.1 ([ROOT]/foo)` +The package foo v0.0.1 ([ROOT]/foo) does not have a bin target with the name `abc`. + +"#]]) + .run(); + + p.change_file( + "build.rs", + r#"fn main() { println!("cargo::rustc-link-arg-bin=abc"); }"#, + ); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[ERROR] invalid instruction `cargo::rustc-link-arg-bin=abc` from build script of `foo v0.0.1 ([ROOT]/foo)` +The instruction should have the form cargo::rustc-link-arg-bin=BIN=ARG + +"#]]) + .run(); +} + +#[cargo_test] +fn cdylib_link_arg_transitive() { + // There was an unintended regression in 1.50 where rustc-link-arg-cdylib + // arguments from dependencies were being applied in the parent package. + // Previously it was silently ignored. + // See https://github.com/rust-lang/cargo/issues/9562 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + bar = {path="bar"} + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("bar/src/lib.rs", "") + .file( + "bar/build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg-cdylib=--bogus"); + } + "#, + ) + .build(); + p.cargo("build -v") + .without_status() + .with_stderr_data( + "\ +... +[COMPILING] bar v1.0.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 bar/build.rs [..] +[RUNNING] `[ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build` +[WARNING] bar@1.0.0: cargo::rustc-link-arg-cdylib was specified in the build script of bar v1.0.0 \ +([ROOT]/foo/bar), but that package does not contain a cdylib target + +Allowing this was an unintended change in the 1.50 release, and may become an error in \ +the future. For more information, see . +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/lib.rs [..] +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]-C link-arg=--bogus[..]` +...", + ) + .run(); +} + +#[cargo_test] +fn link_arg_transitive_not_allowed() { + // Verify that transitive dependencies don't pass link args. + // + // Note that rustc-link-arg doesn't have any errors or warnings when it is + // unused. Perhaps that could be more aggressive, but it is difficult + // since it could be used for test binaries. + Package::new("bar", "1.0.0") + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg=--bogus"); + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["cdylib"] + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[COMPILING] bar v1.0.0 +[RUNNING] `rustc --crate-name build_script_build [..] +[RUNNING] `[ROOT]/foo/target/debug/build/bar-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name bar [..] +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stderr_does_not_contain("--bogus") + .run(); +} + +#[cargo_test] +fn link_arg_with_doctest() { + let p = project() + .file( + "src/lib.rs", + r#" + //! ``` + //! let x = 5; + //! assert_eq!(x, 5); + //! ``` + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("test --doc -v") + .without_status() + .with_stderr_data( + "\ +... +[RUNNING] `rustdoc [..]--crate-name foo [..]-C link-arg=--this-is-a-bogus-flag[..] +...", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_arg_tests() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file("tests/test_foo.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg-tests=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("test -v") + .without_status() + .with_stderr_data( + "\ +... +[RUNNING] `rustc --crate-name test_foo [..]-C link-arg=--this-is-a-bogus-flag[..] +...", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_arg_benches() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file("benches/bench_foo.rs", "") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg-benches=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("bench -v") + .without_status() + .with_stderr_data( + "\ +... +[RUNNING] `rustc --crate-name bench_foo [..]-C link-arg=--this-is-a-bogus-flag[..] +...", + ) + .run(); +} + +#[cargo_test] +fn build_script_extra_link_arg_examples() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file("examples/example_foo.rs", "fn main() {}") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-link-arg-examples=--this-is-a-bogus-flag"); + } + "#, + ) + .build(); + + p.cargo("build -v --examples") + .without_status() + .with_stderr_data( + "\ +... +[RUNNING] `rustc --crate-name example_foo [..]-C link-arg=--this-is-a-bogus-flag[..] +...", + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_lock.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_lock.rs new file mode 100644 index 000000000..3f3710fc7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_lock.rs @@ -0,0 +1,307 @@ +//! Tests for `CacheLock`. + +use std::thread::JoinHandle; + +use cargo::util::cache_lock::{CacheLockMode, CacheLocker}; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::{retry, thread_wait_timeout, threaded_timeout}; + +use crate::config::GlobalContextBuilder; + +/// Helper to verify that it is OK to acquire the given lock (it shouldn't block). +fn verify_lock_is_ok(mode: CacheLockMode) { + let root = paths::root(); + threaded_timeout(10, move || { + let gctx = GlobalContextBuilder::new().root(root).build(); + let locker = CacheLocker::new(); + // This would block if it is held. + let _lock = locker.lock(&gctx, mode).unwrap(); + assert!(locker.is_locked(mode)); + }); +} + +/// Helper to acquire two locks from the same locker. +fn a_b_nested(a: CacheLockMode, b: CacheLockMode) { + let gctx = GlobalContextBuilder::new().build(); + let locker = CacheLocker::new(); + let lock1 = locker.lock(&gctx, a).unwrap(); + assert!(locker.is_locked(a)); + let lock2 = locker.lock(&gctx, b).unwrap(); + assert!(locker.is_locked(b)); + drop(lock2); + drop(lock1); + // Verify locks were unlocked. + verify_lock_is_ok(CacheLockMode::Shared); + verify_lock_is_ok(CacheLockMode::DownloadExclusive); + verify_lock_is_ok(CacheLockMode::MutateExclusive); +} + +/// Helper to acquire two locks from separate lockers, verifying that they +/// don't block each other. +fn a_then_b_separate_not_blocked(a: CacheLockMode, b: CacheLockMode, verify: CacheLockMode) { + let gctx = GlobalContextBuilder::new().build(); + let locker1 = CacheLocker::new(); + let lock1 = locker1.lock(&gctx, a).unwrap(); + assert!(locker1.is_locked(a)); + let locker2 = CacheLocker::new(); + let lock2 = locker2.lock(&gctx, b).unwrap(); + assert!(locker2.is_locked(b)); + let thread = verify_lock_would_block(verify); + // Unblock the thread. + drop(lock1); + drop(lock2); + // Verify the thread is unblocked. + thread_wait_timeout::<()>(100, thread); +} + +/// Helper to acquire two locks from separate lockers, verifying that the +/// second one blocks. +fn a_then_b_separate_blocked(a: CacheLockMode, b: CacheLockMode) { + let gctx = GlobalContextBuilder::new().build(); + let locker = CacheLocker::new(); + let lock = locker.lock(&gctx, a).unwrap(); + assert!(locker.is_locked(a)); + let thread = verify_lock_would_block(b); + // Unblock the thread. + drop(lock); + // Verify the thread is unblocked. + thread_wait_timeout::<()>(100, thread); +} + +/// Helper to verify that acquiring the given mode would block. +/// +/// Always call `thread_wait_timeout` on the result. +#[must_use] +fn verify_lock_would_block(mode: CacheLockMode) -> JoinHandle<()> { + let root = paths::root(); + // Spawn a thread that will block on the lock. + let thread = std::thread::spawn(move || { + let gctx = GlobalContextBuilder::new().root(root).build(); + let locker2 = CacheLocker::new(); + let lock2 = locker2.lock(&gctx, mode).unwrap(); + assert!(locker2.is_locked(mode)); + drop(lock2); + }); + // Verify that it blocked. + retry(100, || { + if let Ok(s) = std::fs::read_to_string(paths::root().join("shell.out")) { + if s.trim().starts_with("Blocking waiting for file lock on") { + return Some(()); + } else { + eprintln!("unexpected output: {s}"); + // Try again, it might have been partially written. + } + } + None + }); + thread +} + +#[test] +fn new_is_unlocked() { + let locker = CacheLocker::new(); + assert!(!locker.is_locked(CacheLockMode::Shared)); + assert!(!locker.is_locked(CacheLockMode::DownloadExclusive)); + assert!(!locker.is_locked(CacheLockMode::MutateExclusive)); +} + +#[cargo_test] +fn multiple_shared() { + // Test that two nested shared locks from the same locker are safe to acquire. + a_b_nested(CacheLockMode::Shared, CacheLockMode::Shared); +} + +#[cargo_test] +fn multiple_shared_separate() { + // Test that two independent shared locks are safe to acquire at the same time. + a_then_b_separate_not_blocked( + CacheLockMode::Shared, + CacheLockMode::Shared, + CacheLockMode::MutateExclusive, + ); +} + +#[cargo_test] +fn multiple_download() { + // That that two nested download locks from the same locker are safe to acquire. + a_b_nested( + CacheLockMode::DownloadExclusive, + CacheLockMode::DownloadExclusive, + ); +} + +#[cargo_test] +fn multiple_mutate() { + // That that two nested mutate locks from the same locker are safe to acquire. + a_b_nested( + CacheLockMode::MutateExclusive, + CacheLockMode::MutateExclusive, + ); +} + +#[cargo_test] +#[should_panic(expected = "lock is not allowed")] +fn download_then_shared() { + // This sequence is not supported. + a_b_nested(CacheLockMode::DownloadExclusive, CacheLockMode::Shared); +} + +#[cargo_test] +#[should_panic(expected = "lock upgrade from shared to exclusive not supported")] +fn shared_then_mutate() { + // This sequence is not supported. + a_b_nested(CacheLockMode::Shared, CacheLockMode::MutateExclusive); +} + +#[cargo_test] +fn shared_then_download() { + a_b_nested(CacheLockMode::Shared, CacheLockMode::DownloadExclusive); + // Verify drop actually unlocked. + verify_lock_is_ok(CacheLockMode::DownloadExclusive); + verify_lock_is_ok(CacheLockMode::MutateExclusive); +} + +#[cargo_test] +fn mutate_then_shared() { + a_b_nested(CacheLockMode::MutateExclusive, CacheLockMode::Shared); + // Verify drop actually unlocked. + verify_lock_is_ok(CacheLockMode::MutateExclusive); +} + +#[cargo_test] +fn download_then_mutate() { + a_b_nested( + CacheLockMode::DownloadExclusive, + CacheLockMode::MutateExclusive, + ); + // Verify drop actually unlocked. + verify_lock_is_ok(CacheLockMode::DownloadExclusive); + verify_lock_is_ok(CacheLockMode::MutateExclusive); +} + +#[cargo_test] +fn mutate_then_download() { + a_b_nested( + CacheLockMode::MutateExclusive, + CacheLockMode::DownloadExclusive, + ); + // Verify drop actually unlocked. + verify_lock_is_ok(CacheLockMode::MutateExclusive); + verify_lock_is_ok(CacheLockMode::DownloadExclusive); +} + +#[cargo_test] +fn readonly() { + // In a permission denied situation, it should still allow a lock. It just + // silently behaves as-if it was locked. + let cargo_home = paths::home().join(".cargo"); + std::fs::create_dir_all(&cargo_home).unwrap(); + let mut perms = std::fs::metadata(&cargo_home).unwrap().permissions(); + perms.set_readonly(true); + std::fs::set_permissions(&cargo_home, perms).unwrap(); + let gctx = GlobalContextBuilder::new().build(); + let locker = CacheLocker::new(); + for mode in [ + CacheLockMode::Shared, + CacheLockMode::DownloadExclusive, + CacheLockMode::MutateExclusive, + ] { + let _lock1 = locker.lock(&gctx, mode).unwrap(); + // Make sure it can recursively acquire the lock, too. + let _lock2 = locker.lock(&gctx, mode).unwrap(); + } +} + +#[cargo_test] +fn download_then_shared_separate() { + a_then_b_separate_not_blocked( + CacheLockMode::DownloadExclusive, + CacheLockMode::Shared, + CacheLockMode::MutateExclusive, + ); +} + +#[cargo_test] +fn shared_then_download_separate() { + a_then_b_separate_not_blocked( + CacheLockMode::Shared, + CacheLockMode::DownloadExclusive, + CacheLockMode::MutateExclusive, + ); +} + +#[cargo_test] +fn multiple_download_separate() { + // Test that with two independent download locks, the second blocks until + // the first is released. + a_then_b_separate_blocked( + CacheLockMode::DownloadExclusive, + CacheLockMode::DownloadExclusive, + ); +} + +#[cargo_test] +fn multiple_mutate_separate() { + // Test that with two independent mutate locks, the second blocks until + // the first is released. + a_then_b_separate_blocked( + CacheLockMode::MutateExclusive, + CacheLockMode::MutateExclusive, + ); +} + +#[cargo_test] +fn shared_then_mutate_separate() { + a_then_b_separate_blocked(CacheLockMode::Shared, CacheLockMode::MutateExclusive); +} + +#[cargo_test] +fn download_then_mutate_separate() { + a_then_b_separate_blocked( + CacheLockMode::DownloadExclusive, + CacheLockMode::MutateExclusive, + ); +} + +#[cargo_test] +fn mutate_then_download_separate() { + a_then_b_separate_blocked( + CacheLockMode::MutateExclusive, + CacheLockMode::DownloadExclusive, + ); +} + +#[cargo_test] +fn mutate_then_shared_separate() { + a_then_b_separate_blocked(CacheLockMode::MutateExclusive, CacheLockMode::Shared); +} + +#[cargo_test(ignore_windows = "no method to prevent creating or locking a file")] +fn mutate_err_is_atomic() { + // Verifies that when getting a mutate lock, that if the first lock + // succeeds, but the second one fails, that the first lock is released. + let gctx = GlobalContextBuilder::new().build(); + let locker = CacheLocker::new(); + let cargo_home = gctx.home().as_path_unlocked(); + let cache_path = cargo_home.join(".package-cache"); + // This is a hacky way to force an error acquiring the download lock. By + // making it a directory, it is unable to open it. + // TODO: Unfortunately this doesn't work on Windows. I don't have any + // ideas on how to simulate an error on Windows. + cache_path.mkdir_p(); + match locker.lock(&gctx, CacheLockMode::MutateExclusive) { + Ok(_) => panic!("did not expect lock to succeed"), + Err(e) => { + let msg = format!("{e:?}"); + assert!(msg.contains("failed to open:"), "{msg}"); + } + } + assert!(!locker.is_locked(CacheLockMode::MutateExclusive)); + assert!(!locker.is_locked(CacheLockMode::DownloadExclusive)); + assert!(!locker.is_locked(CacheLockMode::Shared)); + cache_path.rm_rf(); + verify_lock_is_ok(CacheLockMode::DownloadExclusive); + verify_lock_is_ok(CacheLockMode::Shared); + verify_lock_is_ok(CacheLockMode::MutateExclusive); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_messages.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_messages.rs new file mode 100644 index 000000000..f5f11a118 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cache_messages.rs @@ -0,0 +1,519 @@ +//! Tests for caching compiler diagnostics. + +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::tools; +use cargo_test_support::{basic_manifest, is_coarse_mtime, project, registry::Package, sleep_ms}; + +use super::messages::raw_rustc_output; + +fn as_str(bytes: &[u8]) -> &str { + std::str::from_utf8(bytes).expect("valid utf-8") +} + +#[cargo_test] +fn simple() { + // A simple example that generates two warnings (unused functions). + let p = project() + .file( + "src/lib.rs", + " + fn a() {} + fn b() {} + ", + ) + .build(); + + // Capture what rustc actually emits. This is done to avoid relying on the + // exact message formatting in rustc. + let rustc_output = raw_rustc_output(&p, "src/lib.rs", &[]); + + // -q so the output is the same as rustc (no "Compiling" or "Finished"). + let cargo_output1 = p.cargo("check -q --color=never").run(); + assert_eq!(rustc_output, as_str(&cargo_output1.stderr)); + assert!(cargo_output1.stdout.is_empty()); + // Check that the cached version is exactly the same. + let cargo_output2 = p.cargo("check -q").run(); + assert_eq!(rustc_output, as_str(&cargo_output2.stderr)); + assert!(cargo_output2.stdout.is_empty()); +} + +// same as `simple`, except everything is using the short format +#[cargo_test] +fn simple_short() { + let p = project() + .file( + "src/lib.rs", + " + fn a() {} + fn b() {} + ", + ) + .build(); + + let rustc_output = raw_rustc_output(&p, "src/lib.rs", &["--error-format=short"]); + + let cargo_output1 = p + .cargo("check -q --color=never --message-format=short") + .run(); + assert_eq!(rustc_output, as_str(&cargo_output1.stderr)); + // assert!(cargo_output1.stdout.is_empty()); + let cargo_output2 = p.cargo("check -q --message-format=short").run(); + println!("{}", String::from_utf8_lossy(&cargo_output2.stdout)); + assert_eq!(rustc_output, as_str(&cargo_output2.stderr)); + assert!(cargo_output2.stdout.is_empty()); +} + +#[cargo_test] +fn color() { + // Check enabling/disabling color. + let p = project().file("src/lib.rs", "fn a() {}").build(); + + // Hack for issue in fwdansi 1.1. It is squashing multiple resets + // into a single reset. + // https://github.com/kennytm/fwdansi/issues/2 + fn normalize(s: &str) -> String { + #[cfg(windows)] + return s.replace("\x1b[0m\x1b[0m", "\x1b[0m"); + #[cfg(not(windows))] + return s.to_string(); + } + + let compare = |a, b| { + assert_eq!(normalize(a), normalize(b)); + }; + + // Capture the original color output. + let rustc_color = raw_rustc_output(&p, "src/lib.rs", &["--color=always"]); + assert!(rustc_color.contains("\x1b[")); + + // Capture the original non-color output. + let rustc_nocolor = raw_rustc_output(&p, "src/lib.rs", &[]); + assert!(!rustc_nocolor.contains("\x1b[")); + + // First pass, non-cached, with color, should be the same. + let cargo_output1 = p.cargo("check -q --color=always").run(); + compare(&rustc_color, as_str(&cargo_output1.stderr)); + + // Replay cached, with color. + let cargo_output2 = p.cargo("check -q --color=always").run(); + compare(&rustc_color, as_str(&cargo_output2.stderr)); + + // Replay cached, no color. + let cargo_output_nocolor = p.cargo("check -q --color=never").run(); + compare(&rustc_nocolor, as_str(&cargo_output_nocolor.stderr)); +} + +#[cargo_test] +fn cached_as_json() { + // Check that cached JSON output is the same. + let p = project().file("src/lib.rs", "fn a() {}").build(); + + // Grab the non-cached output, feature disabled. + // NOTE: When stabilizing, this will need to be redone. + let cargo_output = p.cargo("check --message-format=json").run(); + let orig_cargo_out = as_str(&cargo_output.stdout); + assert!(orig_cargo_out.contains("compiler-message")); + p.cargo("clean").run(); + + // Check JSON output, not fresh. + let cargo_output1 = p.cargo("check --message-format=json").run(); + assert_eq!(as_str(&cargo_output1.stdout), orig_cargo_out); + + // Check JSON output, fresh. + let cargo_output2 = p.cargo("check --message-format=json").run(); + // The only difference should be this field. + let fix_fresh = as_str(&cargo_output2.stdout).replace("\"fresh\":true", "\"fresh\":false"); + assert_eq!(fix_fresh, orig_cargo_out); +} + +#[cargo_test] +fn clears_cache_after_fix() { + // Make sure the cache is invalidated when there is no output. + let p = project().file("src/lib.rs", "fn asdf() {}").build(); + // Fill the cache. + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] function `asdf` is never used +... +[WARNING] `foo` (lib) generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + let cpath = p + .glob("target/debug/.fingerprint/foo-*/output-*") + .next() + .unwrap() + .unwrap(); + assert!(std::fs::read_to_string(cpath).unwrap().contains("asdf")); + + // Fix it. + if is_coarse_mtime() { + sleep_ms(1000); + } + p.change_file("src/lib.rs", ""); + + p.cargo("check") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_eq!( + p.glob("target/debug/.fingerprint/foo-*/output-*").count(), + 0 + ); + + // And again, check the cache is correct. + p.cargo("check") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc() { + // Create a warning in rustdoc. + let p = project() + .file( + "src/lib.rs", + " + #![warn(missing_docs)] + pub fn f() {} + ", + ) + .build(); + + let rustdoc_output = p.cargo("doc -q --color=always").run(); + let rustdoc_stderr = as_str(&rustdoc_output.stderr); + assert!(rustdoc_stderr.contains("missing")); + assert!(rustdoc_stderr.contains("\x1b[")); + assert_eq!( + p.glob("target/debug/.fingerprint/foo-*/output-*").count(), + 1 + ); + + // Check the cached output. + let rustdoc_output = p.cargo("doc -q --color=always").run(); + assert_eq!(as_str(&rustdoc_output.stderr), rustdoc_stderr); +} + +#[cargo_test] +fn fix() { + // Make sure `fix` is not broken by caching. + let p = project().file("src/lib.rs", "pub fn try() {}").build(); + + p.cargo("fix --edition --allow-no-vcs").run(); + + assert_eq!(p.read_file("src/lib.rs"), "pub fn r#try() {}"); +} + +#[cargo_test] +fn very_verbose() { + // Handle cap-lints in dependencies. + Package::new("bar", "1.0.0") + .file("src/lib.rs", "fn not_used() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -vv") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] bar v1.0.0 +[RUNNING] [..] +[WARNING] function `not_used` is never used +... +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check -vv") + .with_stderr_data(str![[r#" +[FRESH] bar v1.0.0 +[WARNING] function `not_used` is never used +... +[WARNING] `bar` (lib) generated 1 warning +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn doesnt_create_extra_files() { + // Ensure it doesn't create `output` files when not needed. + Package::new("dep", "1.0.0") + .file("src/lib.rs", "fn unused() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); + + assert_eq!( + p.glob("target/debug/.fingerprint/foo-*/output-*").count(), + 0 + ); + assert_eq!( + p.glob("target/debug/.fingerprint/dep-*/output-*").count(), + 0 + ); + if is_coarse_mtime() { + sleep_ms(1000); + } + p.change_file("src/lib.rs", "fn unused() {}"); + p.cargo("check").run(); + assert_eq!( + p.glob("target/debug/.fingerprint/foo-*/output-*").count(), + 1 + ); +} + +#[cargo_test] +fn replay_non_json() { + // Handles non-json output. + let rustc = project() + .at("rustc") + .file("Cargo.toml", &basic_manifest("rustc_alt", "1.0.0")) + .file( + "src/main.rs", + r#" + fn main() { + eprintln!("line 1"); + eprintln!("line 2"); + let r = std::process::Command::new("rustc") + .args(std::env::args_os().skip(1)) + .status(); + std::process::exit(r.unwrap().code().unwrap_or(2)); + } + "#, + ) + .build(); + rustc.cargo("build").run(); + let p = project().file("src/lib.rs", "").build(); + p.cargo("check") + .env("RUSTC", rustc.bin("rustc_alt")) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +line 1 +line 2 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .env("RUSTC", rustc.bin("rustc_alt")) + .with_stderr_data(str![[r#" +line 1 +line 2 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn caching_large_output() { + // Handles large number of messages. + // This is an arbitrary amount that is greater than the 100 used in + // job_queue. This is here to check for deadlocks or any other problems. + const COUNT: usize = 250; + let rustc = project() + .at("rustc") + .file("Cargo.toml", &basic_manifest("rustc_alt", "1.0.0")) + .file( + "src/main.rs", + &format!( + r#" + fn main() {{ + for i in 0..{} {{ + eprintln!("{{{{\"message\": \"test message {{}}\", \"level\": \"warning\", \ + \"spans\": [], \"children\": [], \"rendered\": \"test message {{}}\"}}}}", + i, i); + }} + let r = std::process::Command::new("rustc") + .args(std::env::args_os().skip(1)) + .status(); + std::process::exit(r.unwrap().code().unwrap_or(2)); + }} + "#, + COUNT + ), + ) + .build(); + + let mut expected = String::new(); + for i in 0..COUNT { + expected.push_str(&format!("test message {}\n", i)); + } + + rustc.cargo("build").run(); + let p = project().file("src/lib.rs", "").build(); + p.cargo("check") + .env("RUSTC", rustc.bin("rustc_alt")) + .with_stderr_data(&format!( + "\ +[CHECKING] foo v0.0.1 ([ROOT]/foo) +{}[WARNING] `foo` (lib) generated 250 warnings +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + expected + )) + .run(); + + p.cargo("check") + .env("RUSTC", rustc.bin("rustc_alt")) + .with_stderr_data(&format!( + "\ +{}[WARNING] `foo` (lib) generated 250 warnings +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + expected + )) + .run(); +} + +#[cargo_test] +fn rustc_workspace_wrapper() { + let p = project() + .file( + "src/lib.rs", + "pub fn f() { assert!(true); }\n\ + fn unused_func() {}", + ) + .build(); + + p.cargo("check -v") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] [..]/rustc-echo-wrapper[EXE] rustc --crate-name foo [..] +WRAPPER CALLED: rustc --crate-name foo --edition=2015 src/lib.rs [..] +[WARNING] function `unused_func` is never used +... +[WARNING] `foo` (lib) generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Check without a wrapper should rebuild + p.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc[..]` +[WARNING] function `unused_func` is never used +... +[WARNING] `foo` (lib) generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + // Again, reading from the cache. + p.cargo("check -v") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +WRAPPER CALLED: rustc [..] +... +[WARNING] `foo` (lib) generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + // And `check` should also be fresh, reading from cache. + p.cargo("check -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[WARNING] function `unused_func` is never used +... +[WARNING] `foo` (lib) generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn wacky_hashless_fingerprint() { + // On Windows, executables don't have hashes. This checks for a bad + // assumption that caused bad caching. + let p = project() + .file("src/bin/a.rs", "fn main() { let unused = 1; }") + .file("src/bin/b.rs", "fn main() {}") + .build(); + p.cargo("check --bin b") + .with_stderr_does_not_contain("[..]unused[..]") + .run(); + p.cargo("check --bin a") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] unused variable: `unused` +... +[WARNING] `foo` (bin "a") generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // This should not pick up the cache from `a`. + p.cargo("check --bin b") + .with_stderr_does_not_contain("[..]unused[..]") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/mod.rs new file mode 100644 index 000000000..e40d56a18 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/mod.rs @@ -0,0 +1,13 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/stdout.term.svg new file mode 100644 index 000000000..1f85d9915 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/help/stdout.term.svg @@ -0,0 +1,108 @@ + + + + + + + Rust's package manager + + + + Usage: cargo [..][OPTIONS] [COMMAND] + + cargo [..][OPTIONS] -Zscript <MANIFEST_RS> [ARGS]... + + + + Options: + + -V, --version Print version info and exit + + --list List installed commands + + --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 + + -C <DIRECTORY> Change to DIRECTORY before doing anything (nightly-only) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + 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 + + 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 + + uninstall Uninstall a Rust binary + + ... See all commands with --list + + + + See 'cargo help <command>' for more information on a specific command. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/mod.rs new file mode 100644 index 000000000..2de0bc570 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/mod.rs @@ -0,0 +1,2 @@ +mod help; +mod z_help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/mod.rs new file mode 100644 index 000000000..e89083984 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["-Z help"]) + .args(["-Z", "help"]) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/stdout.term.svg new file mode 100644 index 000000000..457002984 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo/z_help/stdout.term.svg @@ -0,0 +1,107 @@ + + + + + + + Available unstable (nightly-only) flags: + + + + -Z allow-features Allow *only* the listed unstable features + + -Z asymmetric-token Allows authenticating with asymmetric tokens + + -Z avoid-dev-deps Avoid installing dev-dependencies if possible + + -Z binary-dep-depinfo Track changes to dependency artifacts + + -Z bindeps Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates + + -Z build-std Enable Cargo to compile the standard library itself as part of a crate graph compilation + + -Z build-std-features Configure features enabled for the standard library itself when building the standard library + + -Z cargo-lints Enable the `[lints.cargo]` table + + -Z checksum-freshness Use a checksum to determine if output is fresh rather than filesystem mtime + + -Z codegen-backend Enable the `codegen-backend` option in profiles in .cargo/config.toml file + + -Z config-include Enable the `include` key in config files + + -Z direct-minimal-versions Resolve minimal dependency versions instead of maximum (direct dependencies only) + + -Z doctest-xcompile Compile and run doctests for non-host target using runner config + + -Z dual-proc-macros Build proc-macros for both the host and the target + + -Z feature-unification Enable new feature unification modes in workspaces + + -Z gc Track cache usage and "garbage collect" unused files + + -Z git Enable support for shallow git fetch operations + + -Z gitoxide Use gitoxide for the given git interactions, or all of them if no argument is given + + -Z host-config Enable the `[host]` section in the .cargo/config.toml file + + -Z minimal-versions Resolve minimal dependency versions instead of maximum + + -Z msrv-policy Enable rust-version aware policy within cargo + + -Z mtime-on-use Configure Cargo to update the mtime of used files + + -Z no-index-update Do not update the registry index even if the cache is outdated + + -Z package-workspace Handle intra-workspace dependencies when packaging + + -Z panic-abort-tests Enable support to run tests with -Cpanic=abort + + -Z profile-rustflags Enable the `rustflags` option in profiles in .cargo/config.toml file + + -Z public-dependency Respect a dependency's `public` field in Cargo.toml to control public/private dependencies + + -Z publish-timeout Enable the `publish.timeout` key in .cargo/config.toml file + + -Z root-dir Set the root directory relative to which paths are printed (defaults to workspace root) + + -Z rustdoc-map Allow passing external documentation mappings to rustdoc + + -Z rustdoc-scrape-examples Allows Rustdoc to scrape code examples from reverse-dependencies + + -Z script Enable support for single-file, `.rs` packages + + -Z target-applies-to-host Enable the `target-applies-to-host` key in the .cargo/config.toml file + + -Z trim-paths Enable the `trim-paths` option in profiles + + -Z unstable-options Allow the usage of unstable options + + -Z warnings Allow use of the build.warnings config key + + + + Run with `cargo -Z [FLAG] [COMMAND]` + + + + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about these flags. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/mod.rs new file mode 100644 index 000000000..850a4a66b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/stderr.term.svg new file mode 100644 index 000000000..70346fd1a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_basic/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/mod.rs new file mode 100644 index 000000000..805d0089c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/stderr.term.svg new file mode 100644 index 000000000..128622970 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_multiple/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v99999.0.0 to dependencies + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/mod.rs new file mode 100644 index 000000000..26f9880be --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.5.4") + .feature("clippy", &[]) + .feature("heapsize", &[]) + .feature("heapsize_impl", &[]) + .feature("nightly", &[]) + .feature("serde", &[]) + .feature("serde_impl", &[]) + .feature("serde_test", &[]) + .alternative(true) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("linked_hash_map --registry alternative") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/stderr.term.svg new file mode 100644 index 000000000..5b040784b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_alter_registry/stderr.term.svg @@ -0,0 +1,51 @@ + + + + + + + Updating `alternative` index + + warning: translating `linked_hash_map` to `linked-hash-map` + + Adding linked-hash-map v0.5.4 to dependencies + + Features: + + - clippy + + - heapsize + + - heapsize_impl + + - nightly + + - serde + + - serde_impl + + - serde_test + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/mod.rs new file mode 100644 index 000000000..5ca79c7c5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cbindgen") + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/stderr.term.svg new file mode 100644 index 000000000..13189fd5c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_no_vendored_package_with_vendor/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: the crate `cbindgen` could not be found in registry index. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/mod.rs new file mode 100644 index 000000000..9220aa7ed --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("+nightly") + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/stderr.term.svg new file mode 100644 index 000000000..b28a8f364 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/add_toolchain/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + error: invalid character `+` in dependency name: `+nightly` + + Use `cargo +nightly add` if you meant to use the `nightly` toolchain. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/mod.rs new file mode 100644 index 000000000..f72db7dd4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-build-package1", "my-build-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--build my-build-package1 my-build-package2") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/stderr.term.svg new file mode 100644 index 000000000..ad278aaf2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-build-package1 v99999.0.0 to build-dependencies + + Adding my-build-package2 v99999.0.0 to build-dependencies + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/mod.rs new file mode 100644 index 000000000..be6f2a685 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .alternative(true) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --build") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/stderr.term.svg new file mode 100644 index 000000000..f7d9173b0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/build_prefer_existing_version/stderr.term.svg @@ -0,0 +1,36 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to build-dependencies + + Features: + + - one + + - two + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/mod.rs new file mode 100644 index 000000000..b60deb2ed --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package2 --rename some-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/stderr.term.svg new file mode 100644 index 000000000..ad09ca226 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/change_rename_target/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package2 v99999.0.0 to optional dependencies + + Adding feature `some-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/mod.rs new file mode 100644 index 000000000..275f7acd4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/mod.rs @@ -0,0 +1,31 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("test_cyclic_features", "0.1.1") + .feature("default", &["feature-one", "feature-two"]) + .feature("feature-one", &["feature-two"]) + .feature("feature-two", &["feature-one"]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("test_cyclic_features") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/stderr.term.svg new file mode 100644 index 000000000..1d9fc9eeb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/cyclic_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding test_cyclic_features v0.1.1 to dependencies + + Features: + + + feature-one + + + feature-two + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/mod.rs new file mode 100644 index 000000000..c08a6bea9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2@0.4.1 --default-features") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/stderr.term.svg new file mode 100644 index 000000000..dd0680b5e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/default_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v0.4.1 to dependencies + + Locking 2 packages to latest compatible versions + + Adding my-package2 v0.4.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/mod.rs new file mode 100644 index 000000000..c25d40d22 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package") + .current_dir(&cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/stderr.term.svg new file mode 100644 index 000000000..a4f9f6c99 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_default_features/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: Use of `default_features` in `my-package` is unsupported, please switch to `default-features` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/mod.rs new file mode 100644 index 000000000..c25d40d22 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package") + .current_dir(&cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/stderr.term.svg new file mode 100644 index 000000000..98a67b972 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/deprecated_section/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: Deprecated dependency sections are unsupported: dev_dependencies, build_dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/mod.rs new file mode 100644 index 000000000..86545d3f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/stderr.term.svg new file mode 100644 index 000000000..890a67bc9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding foo (workspace) to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/mod.rs new file mode 100644 index 000000000..197df7811 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar", "--features", "test"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/stderr.term.svg new file mode 100644 index 000000000..99c2be363 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_features/stderr.term.svg @@ -0,0 +1,46 @@ + + + + + + + Adding foo (workspace) to dependencies + + Features as of v0.0.0: + + + default-base + + + default-merge-base + + + default-test-base + + + merge + + + merge-base + + + test + + + test-base + + - unrelated + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/mod.rs new file mode 100644 index 000000000..d9f519322 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar", "--optional"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/stderr.term.svg new file mode 100644 index 000000000..c8ef4f9c9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_optional/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding foo (workspace) to optional dependencies + + Adding feature `foo` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/mod.rs new file mode 100644 index 000000000..95ecd0d65 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .masquerade_as_nightly_cargo(&["path-base"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/stderr.term.svg new file mode 100644 index 000000000..890a67bc9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_path_base/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding foo (workspace) to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs new file mode 100644 index 000000000..3d2424ebf --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar", "--public"]) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.term.svg new file mode 100644 index 000000000..170ace314 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/detect_workspace_inherit_public/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding foo (workspace) to public dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/mod.rs new file mode 100644 index 000000000..00f9bd8fd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-dev-package1", "my-dev-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--dev my-dev-package1 my-dev-package2") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/stderr.term.svg new file mode 100644 index 000000000..c9db5a2bd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-dev-package1 v99999.0.0 to dev-dependencies + + Adding my-dev-package2 v99999.0.0 to dev-dependencies + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/mod.rs new file mode 100644 index 000000000..f4bb8786a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --dev --build") + .current_dir(cwd) + .assert() + .code(1) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/stderr.term.svg new file mode 100644 index 000000000..4dc6b2515 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_build_conflict/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + error: the argument '--dev' cannot be used with '--build' + + + + Usage: cargo add [OPTIONS] <DEP>[@<VERSION>] ... + + cargo add [OPTIONS] --path <PATH> ... + + cargo add [OPTIONS] --git <URL> ... + + + + For more information, try '--help'. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/in/.cargo/config.toml b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/in/.cargo/config.toml new file mode 100644 index 000000000..4539a4384 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/in/.cargo/config.toml @@ -0,0 +1,2 @@ +[path-bases] +my_base = "." diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/mod.rs new file mode 100644 index 000000000..be1a85503 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --dev") + .current_dir(&cwd) + .masquerade_as_nightly_cargo(&["path-base"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/stderr.term.svg new file mode 100644 index 000000000..c4a8bc014 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_existing_path_base/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dev-dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/mod.rs new file mode 100644 index 000000000..95391cb16 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .alternative(true) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --dev") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/stderr.term.svg new file mode 100644 index 000000000..2fb1ec16d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dev_prefer_existing_version/stderr.term.svg @@ -0,0 +1,36 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dev-dependencies + + Features as of v0.0.0: + + - one + + - two + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/mod.rs new file mode 100644 index 000000000..515e975bc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --dry-run") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/stderr.term.svg new file mode 100644 index 000000000..476f48b82 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/dry_run/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + warning: aborting add due to dry run + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/mod.rs new file mode 100644 index 000000000..5e1c51403 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("@1.2.3") + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/stderr.term.svg new file mode 100644 index 000000000..710039d43 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/empty_dep_name/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: package name cannot be empty + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/mod.rs new file mode 100644 index 000000000..468587d7c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --features eyes") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/stderr.term.svg new file mode 100644 index 000000000..714add361 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + + eyes + + - ears + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs new file mode 100644 index 000000000..41075a98a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; +use itertools::Itertools; + +#[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(current_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_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/stderr.term.svg new file mode 100644 index 000000000..bead185fa --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_activated_over_limit/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + 100 activated features + + 100 deactivated features + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs new file mode 100644 index 000000000..cce0d9042 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; +use itertools::Itertools; + +#[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(current_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_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.term.svg new file mode 100644 index 000000000..1f00dcf69 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_deactivated_over_limit/stderr.term.svg @@ -0,0 +1,95 @@ + + + + + + + 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 + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/mod.rs new file mode 100644 index 000000000..f7071d44d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --features ''") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/stderr.term.svg new file mode 100644 index 000000000..259352b0e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_empty/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + - ears + + - eyes + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/mod.rs new file mode 100644 index 000000000..e149dc009 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --features eyes --features nose") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/stderr.term.svg new file mode 100644 index 000000000..d2400ae42 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_multiple_occurrences/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + + eyes + + + nose + + - ears + + - mouth + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/mod.rs new file mode 100644 index 000000000..0434d5bce --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/stderr.term.svg new file mode 100644 index 000000000..714add361 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_preserve/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + + eyes + + - ears + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/mod.rs new file mode 100644 index 000000000..4a689e723 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --features eyes,nose") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/stderr.term.svg new file mode 100644 index 000000000..d2400ae42 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_spaced_values/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + + eyes + + + nose + + - ears + + - mouth + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/mod.rs new file mode 100644 index 000000000..dc60e5dac --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --features noze") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/stderr.term.svg new file mode 100644 index 000000000..045e9dc9a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown/stderr.term.svg @@ -0,0 +1,36 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + error: unrecognized feature for crate your-face: noze + + disabled features: + + ears, eyes, mouth, nose + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/mod.rs new file mode 100644 index 000000000..b0e229d8d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --features noze") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/stderr.term.svg new file mode 100644 index 000000000..850138396 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/features_unknown_no_features/stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + error: unrecognized feature for crate my-package: noze + + no features available for crate my-package + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/mod.rs new file mode 100644 index 000000000..cd8e4c388 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/mod.rs @@ -0,0 +1,35 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["git-package", "--git", &git_url]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/stderr.term.svg new file mode 100644 index 000000000..bc01d8268 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Adding git-package (git) to dependencies + + Updating git repository `[ROOTURL]/git-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/mod.rs new file mode 100644 index 000000000..e0b7049be --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let (git_dep, git_repo) = cargo_test_support::git::new_repo("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let branch = "dev"; + let find_head = || (git_repo.head().unwrap().peel_to_commit().unwrap()); + git_repo.branch(branch, &find_head(), false).unwrap(); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["git-package", "--git", &git_url, "--branch", branch]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/stderr.term.svg new file mode 100644 index 000000000..bc01d8268 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_branch/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Adding git-package (git) to dependencies + + Updating git repository `[ROOTURL]/git-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/mod.rs new file mode 100644 index 000000000..f0f031e8e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/mod.rs @@ -0,0 +1,41 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args([ + "my-package@0.4.3", + "--git", + "https://github.com/dcjanus/invalid", + ]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/stderr.term.svg new file mode 100644 index 000000000..543d07dc2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_conflicts_namever/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: cannot specify a git URL (`https://github.com/dcjanus/invalid`) with a version (`0.4.3`). + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/mod.rs new file mode 100644 index 000000000..c0f6c6972 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/mod.rs @@ -0,0 +1,35 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["git-package", "--git", &git_url, "--dev"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/stderr.term.svg new file mode 100644 index 000000000..bdc2976ce --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_dev/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Adding git-package (git) to dev-dependencies + + Updating git repository `[ROOTURL]/git-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/mod.rs new file mode 100644 index 000000000..d11d31986 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/mod.rs @@ -0,0 +1,35 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["--git", &git_url]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/stderr.term.svg new file mode 100644 index 000000000..34cf73183 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Updating git repository `[ROOTURL]/git-package` + + Adding git-package (git) to dependencies + + Updating git repository `[ROOTURL]/git-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/mod.rs new file mode 100644 index 000000000..0ee595b87 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/mod.rs @@ -0,0 +1,75 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file( + "p1/Cargo.toml", + &cargo_test_support::basic_manifest("my-package1", "0.3.0+my-package1"), + ) + .file("p1/src/lib.rs", "") + .file( + "p2/Cargo.toml", + &cargo_test_support::basic_manifest("my-package2", "0.3.0+my-package2"), + ) + .file("p2/src/lib.rs", "") + .file( + "p3/Cargo.toml", + &cargo_test_support::basic_manifest("my-package3", "0.3.0+my-package2"), + ) + .file("p3/src/lib.rs", "") + .file( + "p4/Cargo.toml", + &cargo_test_support::basic_manifest("my-package4", "0.3.0+my-package2"), + ) + .file("p4/src/lib.rs", "") + .file( + "p5/Cargo.toml", + &cargo_test_support::basic_manifest("my-package5", "0.3.0+my-package2"), + ) + .file("p5/src/lib.rs", "") + .file( + "p6/Cargo.toml", + &cargo_test_support::basic_manifest("my-package6", "0.3.0+my-package2"), + ) + .file("p6/src/lib.rs", "") + .file( + "p7/Cargo.toml", + &cargo_test_support::basic_manifest("my-package7", "0.3.0+my-package2"), + ) + .file("p7/src/lib.rs", "") + .file( + "p8/Cargo.toml", + &cargo_test_support::basic_manifest("my-package8", "0.3.0+my-package2"), + ) + .file("p8/src/lib.rs", "") + .file( + "p9/Cargo.toml", + &cargo_test_support::basic_manifest("my-package9", "0.3.0+my-package2"), + ) + .file("p9/src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["--git", &git_url]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/stderr.term.svg new file mode 100644 index 000000000..466f7993d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_inferred_name_multiple/stderr.term.svg @@ -0,0 +1,36 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + error: multiple packages found at `[ROOTURL]/git-package`: + + my-package1, my-package2, my-package3, my-package4, my-package5, my-package6 + + my-package7, my-package8, my-package9 + + To disambiguate, run `cargo add --git [ROOTURL]/git-package <package>` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/mod.rs new file mode 100644 index 000000000..1747b81f0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/mod.rs @@ -0,0 +1,53 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file( + "p1/Cargo.toml", + &cargo_test_support::basic_manifest("my-package1", "0.3.0+my-package1"), + ) + .file("p1/src/lib.rs", "") + .file( + "p2/Cargo.toml", + &cargo_test_support::basic_manifest("my-package2", "0.3.0+my-package2"), + ) + .file("p2/src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["my-package1", "my-package2", "--git", &git_url]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/stderr.term.svg new file mode 100644 index 000000000..15095587c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_names/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Adding my-package1 (git) to dependencies + + Adding my-package2 (git) to dependencies + + Updating git repository `[ROOTURL]/git-package` + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/mod.rs new file mode 100644 index 000000000..18c7ce4a5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/mod.rs @@ -0,0 +1,64 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let main_manifest = r#" + [package] + name = "main-package" + version = "0.1.1+main-package" + authors = [] + + [workspace] + members = ["package-wo-feature", "package-with-feature"] + "#; + + let manifest_feature = r#" + [package] + name = "package-with-feature" + version = "0.1.3+package-with-feature" + [features] + target_feature = [] + "#; + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file("Cargo.toml", &main_manifest) + .file( + "package-wo-feature/Cargo.toml", + &cargo_test_support::basic_manifest( + "package-wo-feature", + "0.1.1+package-wo-feature", + ), + ) + .file("package-wo-feature/src/lib.rs", "") + .file("package-with-feature/Cargo.toml", &manifest_feature) + .file("package-with-feature/src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args([ + "--git", + &git_url, + "package-with-feature", + "--features=target_feature", + ]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/stderr.term.svg new file mode 100644 index 000000000..c1d520504 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_multiple_packages_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Adding package-with-feature (git) to dependencies + + Features: + + + target_feature + + Updating git repository `[ROOTURL]/git-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/mod.rs new file mode 100644 index 000000000..b1e5e6246 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/mod.rs @@ -0,0 +1,54 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("versioned-package", ver) + .alternative(true) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("versioned-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("versioned-package", "0.3.0+versioned-package"), + ) + .file("src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args([ + "versioned-package", + "--git", + &git_url, + "--registry", + "alternative", + ]) + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/stderr.term.svg new file mode 100644 index 000000000..094b9725a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_registry/stderr.term.svg @@ -0,0 +1,38 @@ + + + + + + + Updating git repository `[ROOTURL]/versioned-package` + + Adding versioned-package (git) to dependencies + + error: failed to parse manifest at `[ROOT]/case/Cargo.toml` + + + + Caused by: + + dependency (versioned-package) specification is ambiguous. Only one of `git` or `registry` is allowed. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/mod.rs new file mode 100644 index 000000000..3cd5759bf --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let (git_dep, git_repo) = cargo_test_support::git::new_repo("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let find_head = || (git_repo.head().unwrap().peel_to_commit().unwrap()); + let head = find_head().id().to_string(); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["git-package", "--git", &git_url, "--rev", &head]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/stderr.term.svg new file mode 100644 index 000000000..bc01d8268 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_rev/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Adding git-package (git) to dependencies + + Updating git repository `[ROOTURL]/git-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/mod.rs new file mode 100644 index 000000000..a29ae6d7d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let (git_dep, git_repo) = cargo_test_support::git::new_repo("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let tag = "v1.0.0"; + cargo_test_support::git::tag(&git_repo, tag); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["git-package", "--git", &git_url, "--tag", tag]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/stderr.term.svg new file mode 100644 index 000000000..bc01d8268 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/git_tag/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + Adding git-package (git) to dependencies + + Updating git repository `[ROOTURL]/git-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/mod.rs new file mode 100644 index 000000000..a93be5e5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/stdout.term.svg new file mode 100644 index 000000000..9309e91ec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/help/stdout.term.svg @@ -0,0 +1,308 @@ + + + + + + + Add dependencies to a Cargo.toml manifest file + + + + Usage: cargo add [OPTIONS] <DEP>[@<VERSION>] ... + + cargo add [OPTIONS] --path <PATH> ... + + cargo add [OPTIONS] --git <URL> ... + + + + Arguments: + + [DEP_ID]... + + Reference to a package to add as a dependency + + + + You can reference a package by: + + - `<name>`, like `cargo add serde` (latest version will be used) + + - `<name>@<version-req>`, like `cargo add serde@1` or `cargo add serde@=1.0.38` + + + + Options: + + --no-default-features + + Disable the default features + + + + --default-features + + Re-enable the default features + + + + -F, --features <FEATURES> + + Space or comma separated list of features to activate + + + + --optional + + Mark the dependency as optional + + + + The package name will be exposed as feature of your crate. + + + + --no-optional + + Mark the dependency as required + + + + The package will be removed from your features. + + + + --public + + Mark the dependency as public (unstable) + + + + The dependency can be referenced in your library's public API. + + + + --no-public + + Mark the dependency as private (unstable) + + + + While you can use the crate in your implementation, it cannot be referenced in your public + + API. + + + + --rename <NAME> + + Rename the dependency + + + + Example uses: + + - Depending on multiple versions of a crate + + - Depend on crates with the same name from different registries + + + + -n, --dry-run + + Don't actually write the manifest + + + + -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 + + + + --config <KEY=VALUE|PATH> + + Override a configuration value + + + + -Z <FLAG> + + Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details + + + + -h, --help + + Print help (see a summary with '-h') + + + + Manifest Options: + + --manifest-path <PATH> + + Path to Cargo.toml + + + + --lockfile-path <PATH> + + Path to Cargo.lock (unstable) + + + + --ignore-rust-version + + Ignore `rust-version` specification in packages + + + + --locked + + Assert that `Cargo.lock` will remain unchanged + + + + --offline + + Run without accessing the network + + + + --frozen + + Equivalent to specifying both --locked and --offline + + + + Package Selection: + + -p, --package [<SPEC>] + + Package to modify + + + + Source: + + --path <PATH> + + Filesystem path to local crate to add + + + + --base <BASE> + + The path base to use when adding from a local crate (unstable). + + + + --git <URI> + + Git repository location + + + + Without any other information, cargo will use latest commit on the main branch. + + + + --branch <BRANCH> + + Git branch to download the crate from + + + + --tag <TAG> + + Git tag to download the crate from + + + + --rev <REV> + + Git reference to download the crate from + + + + This is the catch all, handling hashes to named references in remote repositories. + + + + --registry <NAME> + + Package registry for this dependency + + + + Section: + + --dev + + Add as development dependency + + + + Dev-dependencies are not used when compiling a package for building, but are used for + + compiling tests, examples, and benchmarks. + + + + These dependencies are not propagated to other packages which depend on this package. + + + + --build + + Add as build dependency + + + + Build-dependencies are the only dependencies available for use by build scripts + + (`build.rs` files). + + + + --target <TARGET> + + Add as dependency to the given target platform + + + + Run `cargo help add` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/mod.rs new file mode 100644 index 000000000..eb9842b2d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("prerelease_only", "0.2.0-alpha.1").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("prerelease_only") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/stderr.term.svg new file mode 100644 index 000000000..554f12a09 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/infer_prerelease/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding prerelease_only v0.2.0-alpha.1 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/mod.rs new file mode 100644 index 000000000..c8ef1f756 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --flag") + .current_dir(cwd) + .assert() + .code(1) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/stderr.term.svg new file mode 100644 index 000000000..82d236ae4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_arg/stderr.term.svg @@ -0,0 +1,46 @@ + + + + + + + error: unexpected argument '--flag' found + + + + tip: a similar argument exists: '--tag' + + + + Usage: cargo add [OPTIONS] <DEP>[@<VERSION>] ... + + cargo add [OPTIONS] --path <PATH> ... + + cargo add [OPTIONS] --git <URL> ... + + + + For more information, try '--help'. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/mod.rs new file mode 100644 index 000000000..0a923250f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/mod.rs @@ -0,0 +1,35 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["not-in-git", "--git", &git_url]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/stderr.term.svg new file mode 100644 index 000000000..fc52c27e3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_git_name/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + error: the crate `not-in-git@[ROOTURL]/git-package` could not be found at `[ROOTURL]/git-package` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/mod.rs new file mode 100644 index 000000000..9aeea1251 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "--default-features", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/stderr.term.svg new file mode 100644 index 000000000..84b42a908 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_inherit_dependency/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: cannot override workspace dependency with `--default-features`, either change `workspace.dependencies.foo.default-features` or define the dependency exclusively in the package's manifest + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/mod.rs new file mode 100644 index 000000000..9aeea1251 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "--default-features", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/stderr.term.svg new file mode 100644 index 000000000..84b42a908 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_overwrite_inherit_dependency/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: cannot override workspace dependency with `--default-features`, either change `workspace.dependencies.foo.default-features` or define the dependency exclusively in the package's manifest + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/mod.rs new file mode 100644 index 000000000..c564fa436 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["--rename", "foo", "foo-alt", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/stderr.term.svg new file mode 100644 index 000000000..d2fb7db39 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_key_rename_inherit_dependency/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: cannot override workspace dependency with `--rename`, either change `workspace.dependencies.foo.package` or define the dependency exclusively in the package's manifest + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/mod.rs new file mode 100644 index 000000000..f404cd2c7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/stderr.term.svg new file mode 100644 index 000000000..0ebf039fc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_manifest/stderr.term.svg @@ -0,0 +1,40 @@ + + + + + + + error: invalid string + + expected `"`, `'` + + --> Cargo.toml:9:7 + + | + + 9 | key = invalid-value + + | ^ + + | + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/mod.rs new file mode 100644 index 000000000..c15f9158c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("lets_hope_nobody_ever_publishes_this_crate") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/stderr.term.svg new file mode 100644 index 000000000..0ebce1720 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_name_external/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating `dummy-registry` index + + error: the crate `lets_hope_nobody_ever_publishes_this_crate` could not be found in registry index. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/mod.rs new file mode 100644 index 000000000..d19260496 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture --path ./tests/fixtures/local") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/stderr.term.svg new file mode 100644 index 000000000..2c332b98a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path/stderr.term.svg @@ -0,0 +1,45 @@ + + + + + + + error: failed to load source for dependency `cargo-list-test-fixture` + + + + Caused by: + + Unable to update [ROOT]/case/tests/fixtures/local + + + + Caused by: + + failed to read `[ROOT]/case/tests/fixtures/local/Cargo.toml` + + + + Caused by: + + [..] + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/mod.rs new file mode 100644 index 000000000..92319f791 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("not-at-path --path ../dependency") + .current_dir(&cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/stderr.term.svg new file mode 100644 index 000000000..4f64a9041 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_name/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: the crate `not-at-path@[ROOT]/case/dependency` could not be found at `[ROOT]/case/dependency` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/mod.rs new file mode 100644 index 000000000..9397c5a6c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture --path .") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/stderr.term.svg new file mode 100644 index 000000000..6ad6a900b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_path_self/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Adding cargo-list-test-fixture (local) to dependencies + + error: cannot add `cargo-list-test-fixture` as a dependency to itself + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/mod.rs new file mode 100644 index 000000000..b3184089e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --target ''") + .current_dir(cwd) + .assert() + .code(1) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/stderr.term.svg new file mode 100644 index 000000000..7179275cc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_target_empty/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + error: a value is required for '--target <TARGET>' but none was supplied + + + + For more information, try '--help'. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/mod.rs new file mode 100644 index 000000000..812be6142 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package@invalid-version-string") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/stderr.term.svg new file mode 100644 index 000000000..44c8a9626 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/invalid_vers/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + error: invalid version requirement `invalid-version-string` + + + + Caused by: + + unexpected character 'i' while parsing major version number + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/mod.rs new file mode 100644 index 000000000..891e0c332 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["your-face"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/stderr.term.svg new file mode 100644 index 000000000..259352b0e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + - ears + + - eyes + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/mod.rs new file mode 100644 index 000000000..401a52f45 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/mod.rs @@ -0,0 +1,43 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --path ../dependency") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/stderr.term.svg new file mode 100644 index 000000000..e11208264 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path/stderr.term.svg @@ -0,0 +1,46 @@ + + + + + + + Adding your-face (local) to dependencies + + Features: + + + mouth + + + nose + + - eyes + + - optional-dependency + + Updating `dummy-registry` index + + Locking 1 package to latest compatible version + + Adding my-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/mod.rs new file mode 100644 index 000000000..e6172c001 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/mod.rs @@ -0,0 +1,48 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args([ + "your-face", + "--path", + "../dependency", + "--no-default-features", + ]) + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/stderr.term.svg new file mode 100644 index 000000000..4e71147a2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/list_features_path_no_default/stderr.term.svg @@ -0,0 +1,46 @@ + + + + + + + Adding your-face (local) to dependencies + + Features: + + - eyes + + - mouth + + - nose + + - optional-dependency + + Updating `dummy-registry` index + + Locking 1 package to latest compatible version + + Adding my-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/mod.rs new file mode 100644 index 000000000..4f3f675c5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --locked") + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/stderr.term.svg new file mode 100644 index 000000000..dd3e844e3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_changed/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + error: the manifest file [ROOT]/case/Cargo.toml needs to be updated but --locked was passed to prevent this + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/mod.rs new file mode 100644 index 000000000..79c44a182 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --locked") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/stderr.term.svg new file mode 100644 index 000000000..67da0f3db --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/locked_unchanged/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/mod.rs new file mode 100644 index 000000000..e256189bf --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package", "unrelateed-crate"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/stderr.term.svg new file mode 100644 index 000000000..ee2eaf696 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/lockfile_updated/stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + Locking 1 package to latest compatible version + + Adding my-package v99999.0.0+my-package + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/mod.rs new file mode 100644 index 000000000..8f8732fd4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/mod.rs @@ -0,0 +1,44 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args([ + "--manifest-path", + "Cargo.toml", + "--package", + "cargo-list-test-fixture", + "cargo-list-test-fixture-dependency", + ]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/stderr.term.svg new file mode 100644 index 000000000..298799cea --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/manifest_path_package/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/mod.rs new file mode 100644 index 000000000..d006d2b65 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/stderr.term.svg new file mode 100644 index 000000000..99c2be363 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/merge_activated_features/stderr.term.svg @@ -0,0 +1,46 @@ + + + + + + + Adding foo (workspace) to dependencies + + Features as of v0.0.0: + + + default-base + + + default-merge-base + + + default-test-base + + + merge + + + merge-base + + + test + + + test-base + + - unrelated + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/mod.rs new file mode 100644 index 000000000..35ab71346 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/mod.rs @@ -0,0 +1,153 @@ +mod add_basic; +mod add_multiple; +mod add_no_vendored_package_with_alter_registry; +mod add_no_vendored_package_with_vendor; +mod add_toolchain; +mod build; +mod build_prefer_existing_version; +mod change_rename_target; +mod cyclic_features; +mod default_features; +mod deprecated_default_features; +mod deprecated_section; +mod detect_workspace_inherit; +mod detect_workspace_inherit_features; +mod detect_workspace_inherit_optional; +mod detect_workspace_inherit_path_base; +mod detect_workspace_inherit_public; +mod dev; +mod dev_build_conflict; +mod dev_existing_path_base; +mod dev_prefer_existing_version; +mod dry_run; +mod empty_dep_name; +mod features; +mod features_activated_over_limit; +mod features_deactivated_over_limit; +mod features_empty; +mod features_multiple_occurrences; +mod features_preserve; +mod features_spaced_values; +mod features_unknown; +mod features_unknown_no_features; +mod git; +mod git_branch; +mod git_conflicts_namever; +mod git_dev; +mod git_inferred_name; +mod git_inferred_name_multiple; +mod git_multiple_names; +mod git_multiple_packages_features; +mod git_registry; +mod git_rev; +mod git_tag; +mod help; +mod infer_prerelease; +mod invalid_arg; +mod invalid_git_name; +mod invalid_key_inherit_dependency; +mod invalid_key_overwrite_inherit_dependency; +mod invalid_key_rename_inherit_dependency; +mod invalid_manifest; +mod invalid_name_external; +mod invalid_path; +mod invalid_path_name; +mod invalid_path_self; +mod invalid_target_empty; +mod invalid_vers; +mod list_features; +mod list_features_path; +mod list_features_path_no_default; +mod locked_changed; +mod locked_unchanged; +mod lockfile_updated; +mod manifest_path_package; +mod merge_activated_features; +mod multiple_conflicts_with_features; +mod multiple_conflicts_with_rename; +mod namever; +mod no_args; +mod no_default_features; +mod no_optional; +mod no_public; +mod normalize_name_git; +mod normalize_name_path; +mod normalize_name_path_existing; +mod normalize_name_registry; +mod normalize_name_registry_existing; +mod normalize_name_registry_yanked; +mod normalize_name_workspace_dep; +mod offline_empty_cache; +mod optional; +mod overwrite_default_features; +mod overwrite_default_features_with_no_default_features; +mod overwrite_features; +mod overwrite_git_with_path; +mod overwrite_inherit_features_noop; +mod overwrite_inherit_noop; +mod overwrite_inherit_optional_noop; +mod overwrite_inline_features; +mod overwrite_name_dev_noop; +mod overwrite_name_noop; +mod overwrite_no_default_features; +mod overwrite_no_default_features_with_default_features; +mod overwrite_no_optional; +mod overwrite_no_optional_with_optional; +mod overwrite_no_public; +mod overwrite_no_public_with_public; +mod overwrite_optional; +mod overwrite_optional_with_no_optional; +mod overwrite_optional_with_optional; +mod overwrite_path_base_with_version; +mod overwrite_path_noop; +mod overwrite_path_with_version; +mod overwrite_preserves_inline_table; +mod overwrite_public; +mod overwrite_public_with_no_public; +mod overwrite_rename_with_no_rename; +mod overwrite_rename_with_rename; +mod overwrite_rename_with_rename_noop; +mod overwrite_version_with_git; +mod overwrite_version_with_path; +mod overwrite_with_rename; +mod overwrite_workspace_dep; +mod overwrite_workspace_dep_features; +mod path; +mod path_base; +mod path_base_inferred_name; +mod path_base_missing_base_path; +mod path_base_unstable; +mod path_dev; +mod path_inferred_name; +mod path_inferred_name_conflicts_full_feature; +mod preserve_dep_std_table; +mod preserve_features_sorted; +mod preserve_features_table; +mod preserve_features_unsorted; +mod preserve_sorted; +mod preserve_unsorted; +mod public; +mod quiet; +mod registry; +mod rename; +mod require_weak; +mod rust_version_ignore; +mod rust_version_incompatible; +mod rust_version_latest; +mod rust_version_older; +mod rustc_ignore; +mod rustc_incompatible; +mod rustc_latest; +mod rustc_older; +mod script_bare; +mod script_frontmatter; +mod script_shebang; +mod sorted_table_with_dotted_item; +mod target; +mod target_cfg; +mod unknown_inherited_feature; +mod vers; +mod workspace_name; +mod workspace_path; +mod workspace_path_dev; +mod yanked; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/mod.rs new file mode 100644 index 000000000..ceea4f171 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/mod.rs @@ -0,0 +1,43 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package1", ver).publish(); + } + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 your-face --features nose") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/stderr.term.svg new file mode 100644 index 000000000..f7692fa9c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_features/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: feature `nose` must be qualified by the dependency it's being activated for, like `my-package1/nose`, `your-face/nose` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/mod.rs new file mode 100644 index 000000000..3ff29dc33 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2 --rename renamed") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/stderr.term.svg new file mode 100644 index 000000000..62ff9d842 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/multiple_conflicts_with_rename/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: cannot specify multiple crates with `--rename` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/mod.rs new file mode 100644 index 000000000..05dc7b6b1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package", "my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1@>=0.1.1 my-package2@0.2.3 my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/stderr.term.svg new file mode 100644 index 000000000..b2faa90be --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/namever/stderr.term.svg @@ -0,0 +1,39 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 >=0.1.1 to dependencies + + Adding my-package2 v0.2.3 to dependencies + + Adding my-package v99999.0.0 to dependencies + + Locking 3 packages to latest compatible versions + + Adding my-package2 v0.2.3+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/mod.rs new file mode 100644 index 000000000..c525cba65 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .current_dir(cwd) + .assert() + .code(1) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/stderr.term.svg new file mode 100644 index 000000000..8fb358ee4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_args/stderr.term.svg @@ -0,0 +1,43 @@ + + + + + + + error: the following required arguments were not provided: + + <DEP_ID|--path <PATH>|--git <URI>> + + + + Usage: cargo add [OPTIONS] <DEP>[@<VERSION>] ... + + cargo add [OPTIONS] --path <PATH> ... + + cargo add [OPTIONS] --git <URL> ... + + + + For more information, try '--help'. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/mod.rs new file mode 100644 index 000000000..73ff19a5b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2@0.4.1 --no-default-features") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/stderr.term.svg new file mode 100644 index 000000000..dd0680b5e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_default_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v0.4.1 to dependencies + + Locking 2 packages to latest compatible versions + + Adding my-package2 v0.4.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/mod.rs new file mode 100644 index 000000000..9f4f9e643 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --no-optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/stderr.term.svg new file mode 100644 index 000000000..eaa9c8600 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_optional/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/mod.rs new file mode 100644 index 000000000..360bac45e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --no-public") + .current_dir(cwd) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/stderr.term.svg new file mode 100644 index 000000000..eaa9c8600 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/no_public/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/mod.rs new file mode 100644 index 000000000..739468a65 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/mod.rs @@ -0,0 +1,35 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("git-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("git-package", "0.3.0+git-package"), + ) + .file("src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["git_package", "--git", &git_url]) + .current_dir(cwd) + .assert() + .failure() // Fuzzy searching for paths isn't supported at this time + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/stderr.term.svg new file mode 100644 index 000000000..8cc5ce688 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_git/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating git repository `[ROOTURL]/git-package` + + error: the crate `git_package@[ROOTURL]/git-package` could not be found at `[ROOTURL]/git-package` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/mod.rs new file mode 100644 index 000000000..717be7aa3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo_list_test_fixture_dependency --path ../dependency") + .current_dir(&cwd) + .assert() + .failure() // Fuzzy searching for paths isn't supported at this time + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/stderr.term.svg new file mode 100644 index 000000000..46323a2d4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: the crate `cargo_list_test_fixture_dependency@[ROOT]/case/dependency` could not be found at `[ROOT]/case/dependency` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/mod.rs new file mode 100644 index 000000000..19c865242 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["fuzzy-name", "-p", "bar"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/stderr.term.svg new file mode 100644 index 000000000..6c9588b1a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_path_existing/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating crates.io index + + error: the crate `fuzzy-name` could not be found in registry index. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/mod.rs new file mode 100644 index 000000000..23c1c5053 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/mod.rs @@ -0,0 +1,42 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.5.4") + .feature("clippy", &[]) + .feature("heapsize", &[]) + .feature("heapsize_impl", &[]) + .feature("nightly", &[]) + .feature("serde", &[]) + .feature("serde_impl", &[]) + .feature("serde_test", &[]) + .publish(); + cargo_test_support::registry::Package::new("inflector", "0.11.4") + .feature("default", &["heavyweight", "lazy_static", "regex"]) + .feature("heavyweight", &[]) + .feature("lazy_static", &[]) + .feature("regex", &[]) + .feature("unstable", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("linked_hash_map Inflector") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/stderr.term.svg new file mode 100644 index 000000000..f4fcd4007 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry/stderr.term.svg @@ -0,0 +1,65 @@ + + + + + + + Updating `dummy-registry` index + + warning: translating `linked_hash_map` to `linked-hash-map` + + warning: translating `Inflector` to `inflector` + + Adding linked-hash-map v0.5.4 to dependencies + + Features: + + - clippy + + - heapsize + + - heapsize_impl + + - nightly + + - serde + + - serde_impl + + - serde_test + + Adding inflector v0.11.4 to dependencies + + Features: + + + heavyweight + + + lazy_static + + + regex + + - unstable + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/mod.rs new file mode 100644 index 000000000..f5d96445b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your_face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/stderr.term.svg new file mode 100644 index 000000000..70eb9fefc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_existing/stderr.term.svg @@ -0,0 +1,45 @@ + + + + + + + warning: translating `your-face` to `your_face` + + Updating `dummy-registry` index + + Adding your_face v99999.0.0 to dependencies + + Features: + + + eyes + + - ears + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/mod.rs new file mode 100644 index 000000000..4b3bedb34 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/mod.rs @@ -0,0 +1,31 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.5.0").publish(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.5.4").publish(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.6.0") + .yanked(true) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("linked_hash_map") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/stderr.term.svg new file mode 100644 index 000000000..4766fc1a7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_registry_yanked/stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + Updating `dummy-registry` index + + warning: translating `linked_hash_map` to `linked-hash-map` + + Adding linked-hash-map v0.5.4 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/mod.rs new file mode 100644 index 000000000..27c061228 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/mod.rs @@ -0,0 +1,29 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + Package::new("fuzzy_dependency", "1.0.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["fuzzy-dependency", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/stderr.term.svg new file mode 100644 index 000000000..a2a8a98f0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/normalize_name_workspace_dep/stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + warning: translating `fuzzy-dependency` to `fuzzy_dependency` + + Updating `dummy-registry` index + + Adding fuzzy_dependency (workspace) to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/mod.rs new file mode 100644 index 000000000..819e017f7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--offline my-package") + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/stderr.term.svg new file mode 100644 index 000000000..a93311cb6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/offline_empty_cache/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: the crate `my-package` could not be found in registry index. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/mod.rs new file mode 100644 index 000000000..425eceaec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/stderr.term.svg new file mode 100644 index 000000000..5bcecc3ca --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/optional/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to optional dependencies + + Adding feature `my-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/mod.rs new file mode 100644 index 000000000..c08a6bea9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2@0.4.1 --default-features") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/stderr.term.svg new file mode 100644 index 000000000..dd0680b5e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v0.4.1 to dependencies + + Locking 2 packages to latest compatible versions + + Adding my-package2 v0.4.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/mod.rs new file mode 100644 index 000000000..73ff19a5b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2@0.4.1 --no-default-features") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/stderr.term.svg new file mode 100644 index 000000000..dd0680b5e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_default_features_with_no_default_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v0.4.1 to dependencies + + Locking 2 packages to latest compatible versions + + Adding my-package2 v0.4.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/mod.rs new file mode 100644 index 000000000..5a16c2416 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --features nose") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/stderr.term.svg new file mode 100644 index 000000000..d2400ae42 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_features/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + + eyes + + + nose + + - ears + + - mouth + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/mod.rs new file mode 100644 index 000000000..3729f9946 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --path ../dependency") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/stderr.term.svg new file mode 100644 index 000000000..430d0e596 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_git_with_path/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to optional dependencies + + Adding feature `cargo-list-test-fixture-dependency` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/mod.rs new file mode 100644 index 000000000..86545d3f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/stderr.term.svg new file mode 100644 index 000000000..9d470ccc0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_features_noop/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Adding foo (workspace) to dependencies + + Features as of v0.0.0: + + + test + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/mod.rs new file mode 100644 index 000000000..86545d3f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/stderr.term.svg new file mode 100644 index 000000000..890a67bc9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_noop/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding foo (workspace) to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/mod.rs new file mode 100644 index 000000000..86545d3f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/stderr.term.svg new file mode 100644 index 000000000..c8ef4f9c9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inherit_optional_noop/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding foo (workspace) to optional dependencies + + Adding feature `foo` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/mod.rs new file mode 100644 index 000000000..212dba2ca --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/mod.rs @@ -0,0 +1,45 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("unrelateed-crate", ver).publish(); + } + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line( + "unrelateed-crate your-face --features your-face/nose,your-face/mouth -Fyour-face/ears", + ) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/stderr.term.svg new file mode 100644 index 000000000..d777800a0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_inline_features/stderr.term.svg @@ -0,0 +1,43 @@ + + + + + + + Updating `dummy-registry` index + + Adding unrelateed-crate v99999.0.0 to dependencies + + Adding your-face v99999.0.0 to dependencies + + Features: + + + ears + + + eyes + + + mouth + + + nose + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/mod.rs new file mode 100644 index 000000000..9ce9a97f7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .alternative(true) + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --dev") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/stderr.term.svg new file mode 100644 index 000000000..3e4aa0e20 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_dev_noop/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Adding your-face (local) to dev-dependencies + + Features: + + + mouth + + + nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/mod.rs new file mode 100644 index 000000000..e735c848a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .alternative(true) + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/stderr.term.svg new file mode 100644 index 000000000..04377cbc9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_name_noop/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Adding your-face (local) to optional dependencies + + Features: + + + mouth + + + nose + + Adding feature `your-face` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/mod.rs new file mode 100644 index 000000000..73ff19a5b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2@0.4.1 --no-default-features") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/stderr.term.svg new file mode 100644 index 000000000..dd0680b5e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v0.4.1 to dependencies + + Locking 2 packages to latest compatible versions + + Adding my-package2 v0.4.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/mod.rs new file mode 100644 index 000000000..c08a6bea9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2@0.4.1 --default-features") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/stderr.term.svg new file mode 100644 index 000000000..dd0680b5e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_default_features_with_default_features/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v0.4.1 to dependencies + + Locking 2 packages to latest compatible versions + + Adding my-package2 v0.4.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs new file mode 100644 index 000000000..9f4f9e643 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --no-optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/stderr.term.svg new file mode 100644 index 000000000..eaa9c8600 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs new file mode 100644 index 000000000..425eceaec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.term.svg new file mode 100644 index 000000000..5bcecc3ca --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_optional_with_optional/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to optional dependencies + + Adding feature `my-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/mod.rs new file mode 100644 index 000000000..360bac45e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --no-public") + .current_dir(cwd) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/stderr.term.svg new file mode 100644 index 000000000..eaa9c8600 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs new file mode 100644 index 000000000..7bee1aa5c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --public") + .current_dir(cwd) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.term.svg new file mode 100644 index 000000000..fdfb40bab --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_no_public_with_public/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to public dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/mod.rs new file mode 100644 index 000000000..425eceaec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/stderr.term.svg new file mode 100644 index 000000000..5bcecc3ca --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to optional dependencies + + Adding feature `my-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs new file mode 100644 index 000000000..917125c78 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --no-optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.term.svg new file mode 100644 index 000000000..259352b0e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_no_optional/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + - ears + + - eyes + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs new file mode 100644 index 000000000..d36043479 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package1", "99999.0.0").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 --optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.term.svg new file mode 100644 index 000000000..c64b6d93c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_optional_with_optional/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to optional dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/in/.cargo/config.toml b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/in/.cargo/config.toml new file mode 100644 index 000000000..4539a4384 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/in/.cargo/config.toml @@ -0,0 +1,2 @@ +[path-bases] +my_base = "." diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/mod.rs new file mode 100644 index 000000000..ade44c07b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/mod.rs @@ -0,0 +1,29 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", "20.0.0") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency@20.0") + .current_dir(&cwd) + .masquerade_as_nightly_cargo(&["path-base"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/stderr.term.svg new file mode 100644 index 000000000..ea8afda68 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_base_with_version/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating `dummy-registry` index + + Adding cargo-list-test-fixture-dependency v20.0 to optional dependencies + + Adding feature `cargo-list-test-fixture-dependency` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/mod.rs new file mode 100644 index 000000000..3a1c58bb5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .alternative(true) + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --path ./dependency") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/stderr.term.svg new file mode 100644 index 000000000..04377cbc9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_noop/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Adding your-face (local) to optional dependencies + + Features: + + + mouth + + + nose + + Adding feature `your-face` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/mod.rs new file mode 100644 index 000000000..a25883cb0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency@20.0") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/stderr.term.svg new file mode 100644 index 000000000..97f168c0d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_path_with_version/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding cargo-list-test-fixture-dependency v20.0 to optional dependencies + + Adding feature `cargo-list-test-fixture-dependency` + + Locking 1 package to latest compatible version + + Adding cargo-list-test-fixture-dependency v20.0.0+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/mod.rs new file mode 100644 index 000000000..5a16c2416 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --features nose") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/stderr.term.svg new file mode 100644 index 000000000..d2400ae42 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_preserves_inline_table/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + + eyes + + + nose + + - ears + + - mouth + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/mod.rs new file mode 100644 index 000000000..7bee1aa5c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --public") + .current_dir(cwd) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/stderr.term.svg new file mode 100644 index 000000000..fdfb40bab --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to public dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs new file mode 100644 index 000000000..360bac45e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --no-public") + .current_dir(cwd) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.term.svg new file mode 100644 index 000000000..eaa9c8600 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_public_with_no_public/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/mod.rs new file mode 100644 index 000000000..e253892b6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("versioned-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("versioned-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/stderr.term.svg new file mode 100644 index 000000000..a0bf3f7f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_no_rename/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating `dummy-registry` index + + Adding versioned-package v99999.0.0 to dependencies + + Locking 2 packages to latest compatible versions + + Adding versioned-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/mod.rs new file mode 100644 index 000000000..f38df3033 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("versioned-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("versioned-package --rename a2") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/stderr.term.svg new file mode 100644 index 000000000..a0bf3f7f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating `dummy-registry` index + + Adding versioned-package v99999.0.0 to dependencies + + Locking 2 packages to latest compatible versions + + Adding versioned-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/mod.rs new file mode 100644 index 000000000..2708ad8c0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("versioned-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("versioned-package --rename a1") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/stderr.term.svg new file mode 100644 index 000000000..021168bfb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_rename_with_rename_noop/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding versioned-package v0.1.1 to optional dependencies + + Adding feature `a1` + + Locking 1 package to latest compatible version + + Adding versioned-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/mod.rs new file mode 100644 index 000000000..43ab3b667 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/mod.rs @@ -0,0 +1,46 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("versioned-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let git_dep = cargo_test_support::git::new("versioned-package", |project| { + project + .file( + "Cargo.toml", + &cargo_test_support::basic_manifest("versioned-package", "0.3.0+versioned-package"), + ) + .file("src/lib.rs", "") + }); + let git_url = git_dep.url().to_string(); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["versioned-package", "--git", &git_url]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/stderr.term.svg new file mode 100644 index 000000000..1ab928435 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_git/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating git repository `[ROOTURL]/versioned-package` + + Adding versioned-package (git) to optional dependencies + + Adding feature `versioned-package` + + Updating git repository `[ROOTURL]/versioned-package` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/mod.rs new file mode 100644 index 000000000..3729f9946 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --path ../dependency") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/stderr.term.svg new file mode 100644 index 000000000..430d0e596 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_version_with_path/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to optional dependencies + + Adding feature `cargo-list-test-fixture-dependency` + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/mod.rs new file mode 100644 index 000000000..05f9ed762 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("versioned-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("versioned-package --rename renamed") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/stderr.term.svg new file mode 100644 index 000000000..a0bf3f7f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_with_rename/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating `dummy-registry` index + + Adding versioned-package v99999.0.0 to dependencies + + Locking 2 packages to latest compatible versions + + Adding versioned-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/mod.rs new file mode 100644 index 000000000..cfd8fcb62 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "--path", "./dependency", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/stderr.term.svg new file mode 100644 index 000000000..4c6655369 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding foo (local) to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/mod.rs new file mode 100644 index 000000000..cfd8fcb62 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "--path", "./dependency", "-p", "bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/stderr.term.svg new file mode 100644 index 000000000..f4cc1b7b7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/overwrite_workspace_dep_features/stderr.term.svg @@ -0,0 +1,46 @@ + + + + + + + Adding foo (local) to dependencies + + Features: + + + default-base + + + default-merge-base + + + default-test-base + + + test + + + test-base + + - merge + + - merge-base + + - unrelated + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/mod.rs new file mode 100644 index 000000000..3729f9946 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --path ../dependency") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/stderr.term.svg new file mode 100644 index 000000000..6781757da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/in/.cargo/config.toml b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/in/.cargo/config.toml new file mode 100644 index 000000000..4539a4384 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/in/.cargo/config.toml @@ -0,0 +1,2 @@ +[path-bases] +my_base = "." diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/mod.rs new file mode 100644 index 000000000..326a76283 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --path ../dependency --base my_base") + .current_dir(&cwd) + .masquerade_as_nightly_cargo(&["path-base"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/stderr.term.svg new file mode 100644 index 000000000..6781757da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/in/.cargo/config.toml b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/in/.cargo/config.toml new file mode 100644 index 000000000..4539a4384 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/in/.cargo/config.toml @@ -0,0 +1,2 @@ +[path-bases] +my_base = "." diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/mod.rs new file mode 100644 index 000000000..005a9d753 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--path ../dependency --base my_base") + .current_dir(&cwd) + .masquerade_as_nightly_cargo(&["path-base"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/stderr.term.svg new file mode 100644 index 000000000..6781757da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_inferred_name/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/mod.rs new file mode 100644 index 000000000..dbae05ad0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--path dependency --base bad_base") + .current_dir(&cwd) + .masquerade_as_nightly_cargo(&["path-base"]) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/stderr.term.svg new file mode 100644 index 000000000..ebe52195f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_missing_base_path/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: path base `bad_base` is undefined. You must add an entry for `bad_base` in the Cargo configuration [path-bases] table. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/mod.rs new file mode 100644 index 000000000..c55fa83a1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--path dependency --base mybase") + .current_dir(&cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/stderr.term.svg new file mode 100644 index 000000000..ca60ce2b3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_base_unstable/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + error: feature `path-bases` is required + + + + The package requires the Cargo feature called `path-bases`, but that feature is not stabilized in this version of Cargo ([..]). + + Consider trying a newer version of Cargo (this may require the nightly release). + + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#path-bases for more information about the status of this feature. + + + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/mod.rs new file mode 100644 index 000000000..49b7901c6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --path ../dependency --dev") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/stderr.term.svg new file mode 100644 index 000000000..c4a8bc014 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_dev/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dev-dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/mod.rs new file mode 100644 index 000000000..ca77e190e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--path ../dependency") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/stderr.term.svg new file mode 100644 index 000000000..6781757da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/mod.rs new file mode 100644 index 000000000..18ee86c93 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--path ../dependency --features your-face/nose") + .current_dir(&cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/stderr.term.svg new file mode 100644 index 000000000..d11de1fc2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/path_inferred_name_conflicts_full_feature/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: `your-face/nose` is unsupported when inferring the crate name, use `nose` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/mod.rs new file mode 100644 index 000000000..7c3381f3e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --no-optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/stderr.term.svg new file mode 100644 index 000000000..259352b0e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_dep_std_table/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + - ears + + - eyes + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/mod.rs new file mode 100644 index 000000000..c82c4a0a0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "99999.0.0+my-package") + .feature("a", &[]) + .feature("b", &[]) + .feature("c", &[]) + .feature("d", &[]) + .feature("e", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package -F d") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/stderr.term.svg new file mode 100644 index 000000000..48676b73a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_sorted/stderr.term.svg @@ -0,0 +1,43 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + Features: + + + a + + + b + + + c + + + d + + + e + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/mod.rs new file mode 100644 index 000000000..7c3381f3e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --no-optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/stderr.term.svg new file mode 100644 index 000000000..259352b0e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_table/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + - ears + + - eyes + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/mod.rs new file mode 100644 index 000000000..d78863863 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "99999.0.0+my-package") + .feature("a", &[]) + .feature("b", &[]) + .feature("c", &[]) + .feature("d", &[]) + .feature("e", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package -F e") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/stderr.term.svg new file mode 100644 index 000000000..48676b73a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_features_unsorted/stderr.term.svg @@ -0,0 +1,43 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + Features: + + + a + + + b + + + c + + + d + + + e + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/mod.rs new file mode 100644 index 000000000..40bc43e82 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package", "versioned-package", "toml"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("toml") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/stderr.term.svg new file mode 100644 index 000000000..95a0398e8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_sorted/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding toml v99999.0.0 to dependencies + + Locking 3 packages to latest compatible versions + + Adding my-package v0.1.1+my-package (available: v99999.0.0+my-package) + + Adding versioned-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/mod.rs new file mode 100644 index 000000000..40bc43e82 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package", "versioned-package", "toml"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("toml") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/stderr.term.svg new file mode 100644 index 000000000..95a0398e8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/preserve_unsorted/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + Adding toml v99999.0.0 to dependencies + + Locking 3 packages to latest compatible versions + + Adding my-package v0.1.1+my-package (available: v99999.0.0+my-package) + + Adding versioned-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/mod.rs new file mode 100644 index 000000000..7bee1aa5c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --public") + .current_dir(cwd) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/stderr.term.svg new file mode 100644 index 000000000..fdfb40bab --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/public/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v0.1.0 to public dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/quiet/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/quiet/mod.rs new file mode 100644 index 000000000..7c409b617 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/quiet/mod.rs @@ -0,0 +1,31 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("--quiet your-face") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(str![""]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/mod.rs new file mode 100644 index 000000000..db8f79b8e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/mod.rs @@ -0,0 +1,41 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::alt_init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver) + .alternative(true) + .publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2 --registry alternative") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/stderr.term.svg new file mode 100644 index 000000000..5614bf58b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/registry/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `alternative` index + + Adding my-package1 v99999.0.0 to dependencies + + Adding my-package2 v99999.0.0 to dependencies + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/mod.rs new file mode 100644 index 000000000..c27075ae0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package --rename renamed") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/stderr.term.svg new file mode 100644 index 000000000..70346fd1a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rename/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/mod.rs new file mode 100644 index 000000000..7c3381f3e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package") + .feature("nose", &[]) + .feature("mouth", &[]) + .feature("eyes", &[]) + .feature("ears", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("your-face --no-optional") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/stderr.term.svg new file mode 100644 index 000000000..259352b0e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/require_weak/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + Updating `dummy-registry` index + + Adding your-face v99999.0.0 to dependencies + + Features: + + - ears + + - eyes + + - mouth + + - nose + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/mod.rs new file mode 100644 index 000000000..39ed54242 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/mod.rs @@ -0,0 +1,34 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.0") + .rust_version("1.66") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.72") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg("--ignore-rust-version") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .code(0) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/stderr.term.svg new file mode 100644 index 000000000..f8bbfb2a2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_ignore/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding rust-version-user v0.2.1 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs new file mode 100644 index 000000000..09d9358c8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.0") + .rust_version("1.66") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.1") + .rust_version("1.66") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.72") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/stderr.term.svg new file mode 100644 index 000000000..8983eae2f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_incompatible/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Updating `dummy-registry` index + + error: no version of crate `rust-version-user` can maintain cargo-list-test-fixture's rust-version of 1.56 + + help: pass `--ignore-rust-version` to select rust-version-user@0.2.1 which requires rustc 1.72 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/mod.rs new file mode 100644 index 000000000..b84c9d339 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.0") + .rust_version("1.66") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.72") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/stderr.term.svg new file mode 100644 index 000000000..cd9ff7e18 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_latest/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding rust-version-user v0.2.1 to dependencies + + Locking 1 package to latest Rust 1.72 compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/mod.rs new file mode 100644 index 000000000..b84c9d339 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.0") + .rust_version("1.66") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.72") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/stderr.term.svg new file mode 100644 index 000000000..d1580f34a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rust_version_older/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + warning: ignoring rust-version-user@0.2.1 (which requires rustc 1.72) to maintain cargo-list-test-fixture's rust-version of 1.70 + + Adding rust-version-user v0.1.0 to dependencies + + Locking 1 package to latest Rust 1.70 compatible version + + Adding rust-version-user v0.1.0 (available: v0.2.1, requires Rust 1.72) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/mod.rs new file mode 100644 index 000000000..4eb3ca475 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.0") + .rust_version("1.30") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.1") + .rust_version("1.30") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.2345") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg("--ignore-rust-version") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .code(0) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/stderr.term.svg new file mode 100644 index 000000000..f86e5c4bb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_ignore/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Updating `dummy-registry` index + + Adding rust-version-user v0.2.1 to dependencies + + Locking 1 package to latest compatible version + + Adding rust-version-user v0.2.1 (requires Rust 1.2345) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/mod.rs new file mode 100644 index 000000000..6ce13b064 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.2345") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/stderr.term.svg new file mode 100644 index 000000000..ecf03af2d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_incompatible/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Updating `dummy-registry` index + + error: no version of crate `rust-version-user` is compatible with rustc [..] + + help: pass `--ignore-rust-version` to select rust-version-user@0.2.1 which requires rustc 1.2345 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/mod.rs new file mode 100644 index 000000000..289bb8cec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.0") + .rust_version("1.30") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.1") + .rust_version("1.30") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.2345") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/stderr.term.svg new file mode 100644 index 000000000..7b86b2ab9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_latest/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + warning: ignoring rust-version-user@0.2.1 (which requires rustc 1.2345) as it is incompatible with rustc [..] + + Adding rust-version-user v0.1.1 to dependencies + + Locking 1 package to latest Rust [..] compatible version + + Adding rust-version-user v0.1.1 (available: v0.2.1, requires Rust 1.2345) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/mod.rs new file mode 100644 index 000000000..289bb8cec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.0") + .rust_version("1.30") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.1.1") + .rust_version("1.30") + .publish(); + cargo_test_support::registry::Package::new("rust-version-user", "0.2.1") + .rust_version("1.2345") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("rust-version-user") + .current_dir(cwd) + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/stderr.term.svg new file mode 100644 index 000000000..7b86b2ab9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/rustc_older/stderr.term.svg @@ -0,0 +1,37 @@ + + + + + + + Updating `dummy-registry` index + + warning: ignoring rust-version-user@0.2.1 (which requires rustc 1.2345) as it is incompatible with rustc [..] + + Adding rust-version-user v0.1.1 to dependencies + + Locking 1 package to latest Rust [..] compatible version + + Adding rust-version-user v0.1.1 (available: v0.2.1, requires Rust 1.2345) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/in/cargo-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/in/cargo-test-fixture.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/in/cargo-test-fixture.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/mod.rs new file mode 100644 index 000000000..ffa6db6c6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["script"]) + .arg("-Zscript") + .arg("add") + .arg_line("--manifest-path cargo-test-fixture.rs my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/out/cargo-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/out/cargo-test-fixture.rs new file mode 100644 index 000000000..caf9ce199 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/out/cargo-test-fixture.rs @@ -0,0 +1,6 @@ +--- +[dependencies] +my-package = "99999.0.0" +--- + +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/stderr.term.svg new file mode 100644 index 000000000..b5c72375b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_bare/stderr.term.svg @@ -0,0 +1,36 @@ + + + + + + + warning: `package.edition` is unspecified, defaulting to `[..]` + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + warning: `package.edition` is unspecified, defaulting to `[..]` + + Locking 1 package to latest [..]compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/in/cargo-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/in/cargo-test-fixture.rs new file mode 100644 index 000000000..129939352 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/in/cargo-test-fixture.rs @@ -0,0 +1,7 @@ +--- +[package] +edition = "2015" +--- + +fn main() { +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/mod.rs new file mode 100644 index 000000000..ffa6db6c6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["script"]) + .arg("-Zscript") + .arg("add") + .arg_line("--manifest-path cargo-test-fixture.rs my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/out/cargo-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/out/cargo-test-fixture.rs new file mode 100644 index 000000000..0be369510 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/out/cargo-test-fixture.rs @@ -0,0 +1,10 @@ +--- +[package] +edition = "2015" + +[dependencies] +my-package = "99999.0.0" +--- + +fn main() { +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/stderr.term.svg new file mode 100644 index 000000000..0be687ce1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_frontmatter/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + Locking 1 package to latest [..]compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/in/cargo-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/in/cargo-test-fixture.rs new file mode 100644 index 000000000..627aa3d89 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/in/cargo-test-fixture.rs @@ -0,0 +1,3 @@ +#!/usr/bin/env cargo + +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/mod.rs new file mode 100644 index 000000000..ffa6db6c6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["script"]) + .arg("-Zscript") + .arg("add") + .arg_line("--manifest-path cargo-test-fixture.rs my-package") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/out/cargo-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/out/cargo-test-fixture.rs new file mode 100644 index 000000000..2abcbf974 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/out/cargo-test-fixture.rs @@ -0,0 +1,7 @@ +#!/usr/bin/env cargo +--- +[dependencies] +my-package = "99999.0.0" +--- + +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/stderr.term.svg new file mode 100644 index 000000000..b5c72375b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/script_shebang/stderr.term.svg @@ -0,0 +1,36 @@ + + + + + + + warning: `package.edition` is unspecified, defaulting to `[..]` + + Updating `dummy-registry` index + + Adding my-package v99999.0.0 to dependencies + + warning: `package.edition` is unspecified, defaulting to `[..]` + + Locking 1 package to latest [..]compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/mod.rs new file mode 100644 index 000000000..2e11221b0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/mod.rs @@ -0,0 +1,44 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in [ + "unrelateed-crate", + "versioned-package", + "toml", + "my-build-package1", + ] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("unrelateed-crate") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/stderr.term.svg new file mode 100644 index 000000000..f2f293d6c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/sorted_table_with_dotted_item/stderr.term.svg @@ -0,0 +1,39 @@ + + + + + + + Updating `dummy-registry` index + + Adding unrelateed-crate v99999.0.0 to dependencies + + Locking 4 packages to latest compatible versions + + Adding my-build-package1 v0.1.1+my-package (available: v99999.0.0+my-package) + + Adding toml v0.1.1+my-package (available: v99999.0.0+my-package) + + Adding versioned-package v0.1.1+my-package (available: v99999.0.0+my-package) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/mod.rs new file mode 100644 index 000000000..90acfc246 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for name in ["my-package1", "my-package2"] { + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new(name, ver).publish(); + } + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package1 my-package2 --target 'cfg(target_os=\"linux\")'") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/stderr.term.svg new file mode 100644 index 000000000..15f82846d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/target_cfg/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package1 v99999.0.0 to dependencies for target `cfg(target_os="linux")` + + Adding my-package2 v99999.0.0 to dependencies for target `cfg(target_os="linux")` + + Locking 2 packages to latest compatible versions + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/mod.rs new file mode 100644 index 000000000..5825d0a7f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .args(["foo", "-p", "bar"]) + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/stderr.term.svg new file mode 100644 index 000000000..dfc9c5082 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/unknown_inherited_feature/stderr.term.svg @@ -0,0 +1,40 @@ + + + + + + + Adding foo (workspace) to dependencies + + error: unrecognized feature for crate foo: not_recognized + + disabled features: + + merge, merge-base, unrelated + + enabled features: + + default-base, default-merge-base, default-test-base + + long-feature-name-because-of-formatting-reasons, test, test-base + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/mod.rs new file mode 100644 index 000000000..6bf38dbf1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("my-package@>=0.1.1") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/stderr.term.svg new file mode 100644 index 000000000..d6007fab4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/vers/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding my-package >=0.1.1 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/mod.rs new file mode 100644 index 000000000..fabd90820 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/stderr.term.svg new file mode 100644 index 000000000..298799cea --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_name/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/mod.rs new file mode 100644 index 000000000..3729f9946 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --path ../dependency") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/stderr.term.svg new file mode 100644 index 000000000..298799cea --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/mod.rs new file mode 100644 index 000000000..49b7901c6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("cargo-list-test-fixture-dependency", ver) + .publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = project_root.join("primary"); + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("cargo-list-test-fixture-dependency --path ../dependency --dev") + .current_dir(&cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/stderr.term.svg new file mode 100644 index 000000000..a09279b9e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/workspace_path_dev/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Adding cargo-list-test-fixture-dependency (local) to dev-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/mod.rs new file mode 100644 index 000000000..050943fe8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/mod.rs @@ -0,0 +1,31 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.5.0").publish(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.5.4").publish(); + cargo_test_support::registry::Package::new("linked-hash-map", "0.6.0") + .yanked(true) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("add") + .arg_line("linked-hash-map") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/stderr.term.svg new file mode 100644 index 000000000..cf47fc90e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_add/yanked/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Adding linked-hash-map v0.5.4 to dependencies + + Locking 1 package to latest compatible version + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_alias_config.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_alias_config.rs new file mode 100644 index 000000000..2ad9d99c3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_alias_config.rs @@ -0,0 +1,497 @@ +//! Tests for `[alias]` config command aliases. + +use std::env; + +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::tools::echo_subcommand; +use cargo_test_support::{basic_bin_manifest, project}; + +#[cargo_test] +fn alias_incorrect_config_type() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b-cargo-test = 5 + "#, + ) + .build(); + + p.cargo("b-cargo-test -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid configuration for key `alias.b-cargo-test` +expected a list, but found a integer for `alias.b-cargo-test` in [ROOT]/foo/.cargo/config.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_malformed_config_string() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b-cargo-test = ` + "#, + ) + .build(); + + p.cargo("b-cargo-test -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not load Cargo configuration + +Caused by: + could not parse TOML configuration in `[ROOT]/foo/.cargo/config.toml` + +Caused by: + TOML parse error at line 3, column 32 + | + 3 | b-cargo-test = ` + | ^ + invalid string + expected `"`, `'` + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_malformed_config_list() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b-cargo-test = [1, 2] + "#, + ) + .build(); + + p.cargo("b-cargo-test -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not load Cargo configuration + +Caused by: + failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml` + +Caused by: + failed to parse key `alias` + +Caused by: + failed to parse key `b-cargo-test` + +Caused by: + expected string but found integer in list + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_config() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b-cargo-test = "build" + "#, + ) + .build(); + + p.cargo("b-cargo-test -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn dependent_alias() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b-cargo-test = "build" + a-cargo-test = ["b-cargo-test", "-v"] + "#, + ) + .build(); + + p.cargo("a-cargo-test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn builtin_alias_shadowing_external_subcommand() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .executable("cargo-t", "") + .build(); + + let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); + paths.push(p.root()); + let path = env::join_paths(paths).unwrap(); + + p.cargo("t") + .env("PATH", &path) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_shadowing_external_subcommand() { + let echo = echo_subcommand(); + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + echo = "build" + "#, + ) + .build(); + + let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); + paths.push(echo.target_debug_dir()); + let path = env::join_paths(paths).unwrap(); + + p.cargo("echo") + .env("PATH", &path) + .with_stderr_data(str![[r#" +[WARNING] user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 . +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn default_args_alias() { + let echo = echo_subcommand(); + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + echo = "echo --flag1 --flag2" + test-1 = "echo" + build = "build --verbose" + "#, + ) + .build(); + + let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); + paths.push(echo.target_debug_dir()); + let path = env::join_paths(paths).unwrap(); + + p.cargo("echo") + .env("PATH", &path) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 . +[ERROR] alias echo has unresolvable recursive definition: echo -> echo + +"#]]) + .run(); + + p.cargo("test-1") + .env("PATH", &path) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] user-defined alias `echo` is shadowing an external subcommand found at: `[ROOT]/cargo-echo/target/debug/cargo-echo[EXE]` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 . +[ERROR] alias test-1 has unresolvable recursive definition: test-1 -> echo -> echo + +"#]]) + .run(); + + // Builtins are not expanded by rule + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn corecursive_alias() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + test-1 = "test-2 --flag1" + test-2 = "test-3 --flag2" + test-3 = "test-1 --flag3" + "#, + ) + .build(); + + p.cargo("test-1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] alias test-1 has unresolvable recursive definition: test-1 -> test-2 -> test-3 -> test-1 + +"#]]) + .run(); + + p.cargo("test-2") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] alias test-2 has unresolvable recursive definition: test-2 -> test-3 -> test-1 -> test-2 + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_list_test() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b-cargo-test = ["build", "--release"] + "#, + ) + .build(); + + p.cargo("b-cargo-test -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_with_flags_config() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b-cargo-test = "build --release" + "#, + ) + .build(); + + p.cargo("b-cargo-test -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_cannot_shadow_builtin_command() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + build = "fetch" + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] user-defined alias `build` is ignored, because it is shadowed by a built-in command +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_override_builtin_alias() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + b = "run" + "#, + ) + .build(); + + p.cargo("b") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn builtin_alias_takes_options() { + // #6381 + let p = project() + .file("src/lib.rs", "") + .file( + "examples/ex1.rs", + r#"fn main() { println!("{}", std::env::args().skip(1).next().unwrap()) }"#, + ) + .build(); + + p.cargo("r --example ex1 -- asdf") + .with_stdout_data(str![[r#" +asdf + +"#]]) + .run(); +} + +#[cargo_test] +fn global_options_with_alias() { + // Check that global options are passed through. + let p = project().file("src/lib.rs", "").build(); + + p.cargo("-v c") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn weird_check() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("-- check --invalid_argument -some-other-argument") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] trailing arguments after built-in command `check` are unsupported: `--invalid_argument -some-other-argument` + +To pass the arguments to the subcommand, remove `--` + +"#]]) + .run(); +} + +#[cargo_test] +fn empty_alias() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + string = "" + array = [] + "#, + ) + .build(); + + p.cargo("string") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] subcommand is required, but `alias.string` is empty + +"#]]) + .run(); + + p.cargo("array") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] subcommand is required, but `alias.array` is empty + +"#]]) + .run(); +} + +#[cargo_test] +fn alias_no_subcommand() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [alias] + a = "--locked" + "#, + ) + .build(); + + p.cargo("a") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] subcommand is required, add a subcommand to the command alias `alias.a` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/mod.rs new file mode 100644 index 000000000..36bef3f10 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("bench") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/stdout.term.svg new file mode 100644 index 000000000..74ef89cfb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/help/stdout.term.svg @@ -0,0 +1,146 @@ + + + + + + + Execute all benchmarks of a local package + + + + Usage: cargo[EXE] bench [OPTIONS] [BENCHNAME] [-- [ARGS]...] + + + + Arguments: + + [BENCHNAME] If specified, only run benches containing this string in their names + + [ARGS]... Arguments for the bench binary + + + + Options: + + --no-run Compile, but don't run benchmarks + + --no-fail-fast Run all benchmarks regardless of failure + + --message-format <FMT> Error format + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to run benchmarks for + + --workspace Benchmark all packages in the workspace + + --exclude <SPEC> Exclude packages from the benchmark + + --all Alias for --workspace (deprecated) + + + + Target Selection: + + --lib Benchmark only this package's library + + --bins Benchmark all binaries + + --bin [<NAME>] Benchmark only the specified binary + + --examples Benchmark all examples + + --example [<NAME>] Benchmark only the specified example + + --tests Benchmark all targets that have `test = true` set + + --test [<NAME>] Benchmark only the specified test target + + --benches Benchmark all targets that have `bench = true` set + + --bench [<NAME>] Benchmark only the specified bench target + + --all-targets Benchmark all targets + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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-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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help bench` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/mod.rs new file mode 100644 index 000000000..28be9d1a7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/mod.rs @@ -0,0 +1,2 @@ +mod help; +mod no_keep_going; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/mod.rs new file mode 100644 index 000000000..5426cc6b1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_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_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/stderr.term.svg new file mode 100644 index 000000000..e90ae8685 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_bench/no_keep_going/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + 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/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/mod.rs new file mode 100644 index 000000000..0dbecdcfe --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("build") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/stdout.term.svg new file mode 100644 index 000000000..803fb0638 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/help/stdout.term.svg @@ -0,0 +1,144 @@ + + + + + + + Compile a local package and all of its dependencies + + + + Usage: cargo[EXE] build [OPTIONS] + + + + Options: + + --future-incompat-report Outputs a future incompatibility report at the end of the build + + --message-format <FMT> Error format + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to build (see `cargo help pkgid`) + + --workspace Build all packages in the workspace + + --exclude <SPEC> Exclude packages from the build + + --all Alias for --workspace (deprecated) + + + + Target Selection: + + --lib Build only this package's library + + --bins Build all binaries + + --bin [<NAME>] Build only the specified binary + + --examples Build all examples + + --example [<NAME>] Build only the specified example + + --tests Build all targets that have `test = true` set + + --test [<NAME>] Build only the specified test target + + --benches Build all targets that have `bench = true` set + + --bench [<NAME>] Build only the specified bench target + + --all-targets Build all targets + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + --target [<TRIPLE>] Build for the target triple + + --target-dir <DIRECTORY> Directory for all generated artifacts + + --artifact-dir <PATH> Copy final artifacts to this directory (unstable) + + --build-plan Output the build plan in JSON (unstable) + + --unit-graph Output build graph in JSON (unstable) + + --timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help build` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_build/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/mod.rs new file mode 100644 index 000000000..b5836078c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("check") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/stdout.term.svg new file mode 100644 index 000000000..eb5998415 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/help/stdout.term.svg @@ -0,0 +1,140 @@ + + + + + + + Check a local package and all of its dependencies for errors + + + + Usage: cargo[EXE] check [OPTIONS] + + + + Options: + + --future-incompat-report Outputs a future incompatibility report at the end of the build + + --message-format <FMT> Error format + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package(s) to check + + --workspace Check all packages in the workspace + + --exclude <SPEC> Exclude packages from the check + + --all Alias for --workspace (deprecated) + + + + Target Selection: + + --lib Check only this package's library + + --bins Check all binaries + + --bin [<NAME>] Check only the specified binary + + --examples Check all examples + + --example [<NAME>] Check only the specified example + + --tests Check all targets that have `test = true` set + + --test [<NAME>] Check only the specified test target + + --benches Check all targets that have `bench = true` set + + --bench [<NAME>] Check only the specified bench target + + --all-targets Check all targets + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + -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-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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help check` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_check/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/mod.rs new file mode 100644 index 000000000..2b4679ba7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("clean") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/stdout.term.svg new file mode 100644 index 000000000..53c4349ba --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/help/stdout.term.svg @@ -0,0 +1,90 @@ + + + + + + + Remove artifacts that cargo has generated in the past + + + + Usage: cargo[EXE] clean [OPTIONS] + + + + Options: + + --doc Whether or not to clean just the documentation directory + + -n, --dry-run Display what would be deleted without deleting anything + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to clean artifacts for + + + + 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-dir <DIRECTORY> Directory for all generated artifacts + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help clean` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_clean/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_command.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_command.rs new file mode 100644 index 000000000..785b7d9c1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_command.rs @@ -0,0 +1,572 @@ +//! Tests for custom cargo commands and other global command features. + +use std::env; +use std::fs; +use std::io::Read; +use std::path::{Path, PathBuf}; +use std::process::Stdio; +use std::str; + +use cargo_test_support::basic_manifest; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::tools::echo_subcommand; +use cargo_test_support::{ + basic_bin_manifest, cargo_exe, cargo_process, paths, project, project_in_home, +}; +use cargo_util::paths::join_paths; + +fn path() -> Vec { + env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect() +} + +#[cargo_test] +fn list_commands_with_descriptions() { + let p = project().build(); + p.cargo("--list") + .with_stdout_data( + "\ +... + b alias: build +... + build Compile a local package and all of its dependencies +... + c alias: check +... + r alias: run +... + read-manifest DEPRECATED: Print a JSON representation of a Cargo.toml manifest. +... + t alias: test +... +", + ) + .run(); +} + +#[cargo_test] +fn list_custom_aliases_with_descriptions() { + let p = project_in_home("proj") + .file( + &paths::home().join(".cargo").join("config"), + r#" + [alias] + myaliasstr = "foo --bar" + myaliasvec = ["foo", "--bar"] + "#, + ) + .build(); + + p.cargo("--list") + .with_stdout_data(str![[r#" +... + myaliasstr alias: foo --bar + myaliasvec alias: foo --bar +... +"#]]) + .run(); +} + +#[cargo_test] +fn list_dedupe() { + let p = project() + .executable(Path::new("path-test-1").join("cargo-dupe"), "") + .executable(Path::new("path-test-2").join("cargo-dupe"), "") + .build(); + + let mut path = path(); + path.push(p.root().join("path-test-1")); + path.push(p.root().join("path-test-2")); + let path = env::join_paths(path.iter()).unwrap(); + + p.cargo("--list") + .env("PATH", &path) + .with_stdout_data(str![[r#" +... + dupe +... +"#]]) + .run(); +} + +#[cargo_test] +fn list_command_looks_at_path() { + let proj = project() + .executable(Path::new("path-test").join("cargo-1"), "") + .build(); + + let mut path = path(); + path.push(proj.root().join("path-test")); + let path = env::join_paths(path.iter()).unwrap(); + let output = cargo_process("-v --list").env("PATH", &path).run(); + let output = str::from_utf8(&output.stdout).unwrap(); + assert!( + output.contains("\n 1 "), + "missing 1: {}", + output + ); +} + +#[cfg(windows)] +#[cargo_test] +fn list_command_looks_at_path_case_mismatch() { + let proj = project() + .executable(Path::new("path-test").join("cargo-1"), "") + .build(); + + let mut path = path(); + path.push(proj.root().join("path-test")); + let path = env::join_paths(path.iter()).unwrap(); + + // See issue #11814: Environment variable names are case-insensitive on Windows. + // We need to check that having "Path" instead of "PATH" is okay. + let output = cargo_process("-v --list") + .env("Path", &path) + .env_remove("PATH") + .run(); + let output = str::from_utf8(&output.stdout).unwrap(); + assert!( + output.contains("\n 1 "), + "missing 1: {}", + output + ); +} + +#[cargo_test] +fn list_command_handles_known_external_commands() { + let p = project() + .executable(Path::new("path-test").join("cargo-fmt"), "") + .build(); + + let fmt_desc = " fmt Formats all bin and lib files of the current crate using rustfmt."; + + // Without path - fmt isn't there + p.cargo("--list") + .env("PATH", "") + .with_stdout_does_not_contain(fmt_desc) + .run(); + + // With path - fmt is there with known description + let mut path = path(); + path.push(p.root().join("path-test")); + let path = env::join_paths(path.iter()).unwrap(); + + p.cargo("--list") + .env("PATH", &path) + .with_stdout_data(str![[r#" +... + fmt Formats all bin and lib files of the current crate using rustfmt. +..."#]]) + .run(); +} + +#[cargo_test] +fn list_command_resolves_symlinks() { + let proj = project() + .symlink(cargo_exe(), Path::new("path-test").join("cargo-2")) + .build(); + + let mut path = path(); + path.push(proj.root().join("path-test")); + let path = env::join_paths(path.iter()).unwrap(); + let output = cargo_process("-v --list").env("PATH", &path).run(); + let output = str::from_utf8(&output.stdout).unwrap(); + assert!( + output.contains("\n 2 "), + "missing 2: {}", + output + ); +} + +#[cargo_test] +fn find_closest_capital_c_to_c() { + cargo_process("C") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `C` + +[HELP] a command with a similar name exists: `c` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `C` with `cargo search cargo-C` + +"#]]) + .run(); +} + +#[cargo_test] +fn find_closest_capital_b_to_b() { + cargo_process("B") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `B` + +[HELP] a command with a similar name exists: `b` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `B` with `cargo search cargo-B` + +"#]]) + .run(); +} + +#[cargo_test] +fn find_closest_biuld_to_build() { + cargo_process("biuld") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `biuld` + +[HELP] a command with a similar name exists: `build` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `biuld` with `cargo search cargo-biuld` + +"#]]) + .run(); + + // But, if we actually have `biuld`, it must work! + // https://github.com/rust-lang/cargo/issues/5201 + Package::new("cargo-biuld", "1.0.0") + .file( + "src/main.rs", + r#" + fn main() { + println!("Similar, but not identical to, build"); + } + "#, + ) + .publish(); + + cargo_process("install cargo-biuld").run(); + cargo_process("biuld") + .with_stdout_data(str![[r#" +Similar, but not identical to, build + +"#]]) + .run(); + cargo_process("--list") + .with_stdout_data(str![[r#" +... + biuld +... + build Compile a local package and all of its dependencies +..."#]]) + .run(); +} + +#[cargo_test] +fn find_closest_alias() { + let root = paths::root(); + let my_home = root.join("my_home"); + fs::create_dir(&my_home).unwrap(); + fs::write( + &my_home.join("config.toml"), + r#" + [alias] + myalias = "build" + "#, + ) + .unwrap(); + + cargo_process("myalais") + .env("CARGO_HOME", &my_home) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `myalais` + +[HELP] a command with a similar name exists: `myalias` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `myalais` with `cargo search cargo-myalais` + +"#]]) + .run(); + + // But, if no alias is defined, it must not suggest one! + cargo_process("myalais") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `myalais` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `myalais` with `cargo search cargo-myalais` + +"#]]) + .run(); +} + +// If a subcommand is more than an edit distance of 3 away, we don't make a suggestion. +#[cargo_test] +fn find_closest_dont_correct_nonsense() { + cargo_process("there-is-no-way-that-there-is-a-command-close-to-this") + .cwd(&paths::root()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `there-is-no-way-that-there-is-a-command-close-to-this` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `there-is-no-way-that-there-is-a-command-close-to-this` with `cargo search cargo-there-is-no-way-that-there-is-a-command-close-to-this` + +"#]]) + .run(); +} + +#[cargo_test] +fn displays_subcommand_on_error() { + cargo_process("invalid-command") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `invalid-command` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `invalid-command` with `cargo search cargo-invalid-command` + +"#]]) + .run(); +} + +#[cargo_test] +fn override_cargo_home() { + let root = paths::root(); + let my_home = root.join("my_home"); + fs::create_dir(&my_home).unwrap(); + fs::write( + &my_home.join("config"), + r#" + [cargo-new] + vcs = "none" + "#, + ) + .unwrap(); + + cargo_process("new foo").env("CARGO_HOME", &my_home).run(); + + assert!(!paths::root().join("foo/.git").is_dir()); + + cargo_process("new foo2").run(); + + assert!(paths::root().join("foo2/.git").is_dir()); +} + +#[cargo_test] +fn cargo_subcommand_env() { + let src = format!( + r#" + use std::env; + + fn main() {{ + println!("{{}}", env::var("{}").unwrap()); + }} + "#, + cargo::CARGO_ENV + ); + + let p = project() + .at("cargo-envtest") + .file("Cargo.toml", &basic_bin_manifest("cargo-envtest")) + .file("src/main.rs", &src) + .build(); + + let target_dir = p.target_debug_dir(); + + p.cargo("build").run(); + assert!(p.bin("cargo-envtest").is_file()); + + let cargo = cargo_exe().canonicalize().unwrap(); + let mut path = path(); + path.push(target_dir.clone()); + let path = env::join_paths(path.iter()).unwrap(); + + cargo_process("envtest") + .env("PATH", &path) + .with_stdout_data(format!("{}\n", cargo.to_str().unwrap()).raw()) + .run(); + + // Check that subcommands inherit an overridden $CARGO + let envtest_bin = target_dir + .join("cargo-envtest") + .with_extension(std::env::consts::EXE_EXTENSION) + .canonicalize() + .unwrap(); + let envtest_bin = envtest_bin.to_str().unwrap(); + cargo_process("envtest") + .env("PATH", &path) + .env(cargo::CARGO_ENV, &envtest_bin) + .with_stdout_data(format!("{}\n", envtest_bin).raw().raw()) + .run(); +} + +#[cargo_test] +fn cargo_cmd_bins_vs_explicit_path() { + // Set up `cargo-foo` binary in two places: inside `$HOME/.cargo/bin` and outside of it + // + // Return paths to both places + fn set_up_cargo_foo() -> (PathBuf, PathBuf) { + let p = project() + .at("cargo-foo") + .file("Cargo.toml", &basic_manifest("cargo-foo", "1.0.0")) + .file( + "src/bin/cargo-foo.rs", + r#"fn main() { println!("INSIDE"); }"#, + ) + .file( + "src/bin/cargo-foo2.rs", + r#"fn main() { println!("OUTSIDE"); }"#, + ) + .build(); + p.cargo("build").run(); + let cargo_bin_dir = paths::home().join(".cargo/bin"); + cargo_bin_dir.mkdir_p(); + let root_bin_dir = paths::root().join("bin"); + root_bin_dir.mkdir_p(); + let exe_name = format!("cargo-foo{}", env::consts::EXE_SUFFIX); + fs::rename(p.bin("cargo-foo"), cargo_bin_dir.join(&exe_name)).unwrap(); + fs::rename(p.bin("cargo-foo2"), root_bin_dir.join(&exe_name)).unwrap(); + + (root_bin_dir, cargo_bin_dir) + } + + let (outside_dir, inside_dir) = set_up_cargo_foo(); + + // If `$CARGO_HOME/bin` is not in a path, prefer it over anything in `$PATH`. + // + // This is the historical behavior we don't want to break. + cargo_process("foo") + .with_stdout_data(str![[r#" +INSIDE + +"#]]) + .run(); + + // When `$CARGO_HOME/bin` is in the `$PATH` + // use only `$PATH` so the user-defined ordering is respected. + { + cargo_process("foo") + .env( + "PATH", + join_paths(&[&inside_dir, &outside_dir], "PATH").unwrap(), + ) + .with_stdout_data(str![[r#" +INSIDE + +"#]]) + .run(); + + cargo_process("foo") + // Note: trailing slash + .env( + "PATH", + join_paths(&[inside_dir.join(""), outside_dir.join("")], "PATH").unwrap(), + ) + .with_stdout_data(str![[r#" +INSIDE + +"#]]) + .run(); + + cargo_process("foo") + .env( + "PATH", + join_paths(&[&outside_dir, &inside_dir], "PATH").unwrap(), + ) + .with_stdout_data(str![[r#" +OUTSIDE + +"#]]) + .run(); + + cargo_process("foo") + // Note: trailing slash + .env( + "PATH", + join_paths(&[outside_dir.join(""), inside_dir.join("")], "PATH").unwrap(), + ) + .with_stdout_data(str![[r#" +OUTSIDE + +"#]]) + .run(); + } +} + +#[cargo_test] +fn cargo_subcommand_args() { + let p = echo_subcommand(); + let cargo_foo_bin = p.bin("cargo-echo"); + assert!(cargo_foo_bin.is_file()); + + let mut path = path(); + path.push(p.target_debug_dir()); + let path = env::join_paths(path.iter()).unwrap(); + + cargo_process("echo bar -v --help") + .env("PATH", &path) + .with_stdout_data(str![[r#" +echo bar -v --help + +"#]]) + .run(); +} + +#[cargo_test] +fn explain() { + cargo_process("--explain E0001") + .with_stdout_data(str![[r#" +... +This error suggests that the expression arm corresponding to the noted pattern[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn closed_output_ok() { + // Checks that closed output doesn't cause an error. + let mut p = cargo_process("--list").build_command(); + p.stdout(Stdio::piped()).stderr(Stdio::piped()); + let mut child = p.spawn().unwrap(); + // Close stdout + drop(child.stdout.take()); + // Read stderr + let mut s = String::new(); + child + .stderr + .as_mut() + .unwrap() + .read_to_string(&mut s) + .unwrap(); + let status = child.wait().unwrap(); + assert!(status.success()); + assert!(s.is_empty(), "{}", s); +} + +#[cargo_test] +fn subcommand_leading_plus_output_contains() { + cargo_process("+nightly") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `+nightly` + +[HELP] invoke `cargo` through `rustup` to handle `+toolchain` directives + +"#]]) + .run(); +} + +#[cargo_test] +fn full_did_you_mean() { + cargo_process("bluid") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `bluid` + +[HELP] a command with a similar name exists: `build` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `bluid` with `cargo search cargo-bluid` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/mod.rs new file mode 100644 index 000000000..c1f51f970 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("config") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/stdout.term.svg new file mode 100644 index 000000000..0ff37d952 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/help/stdout.term.svg @@ -0,0 +1,66 @@ + + + + + + + Inspect configuration values + + + + Usage: cargo[EXE] config [OPTIONS] <COMMAND> + + + + Commands: + + get + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/mod.rs new file mode 100644 index 000000000..174fb1841 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_config/mod.rs @@ -0,0 +1,580 @@ +//! Tests for the `cargo config` command. + +use super::config::write_config_at; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use std::fs; +use std::path::PathBuf; + +mod help; + +fn cargo_process(s: &str) -> cargo_test_support::Execs { + let mut p = cargo_test_support::cargo_process(s); + // Clear out some of the environment added by the default cargo_process so + // the tests don't need to deal with it. + p.env_remove("CARGO_PROFILE_DEV_SPLIT_DEBUGINFO") + .env_remove("CARGO_PROFILE_TEST_SPLIT_DEBUGINFO") + .env_remove("CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO") + .env_remove("CARGO_PROFILE_BENCH_SPLIT_DEBUGINFO") + .env_remove("CARGO_INCREMENTAL"); + p +} + +#[cargo_test] +fn gated() { + cargo_process("config get") + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `cargo config` command is unstable, pass `-Z unstable-options` to enable it +See https://github.com/rust-lang/cargo/issues/9301 for more information about the `cargo config` command. + +"#]]) + .run(); +} + +fn common_setup() -> PathBuf { + write_config_at( + paths::home().join(".cargo/config.toml"), + " + [alias] + foo = \"abc --xyz\" + [build] + jobs = 99 + rustflags = [\"--flag-global\"] + [profile.dev] + opt-level = 3 + [profile.dev.package.foo] + opt-level = 1 + [target.'cfg(target_os = \"linux\")'] + runner = \"runme\" + + # How unknown keys are handled. + [extra-table] + somekey = \"somevalue\" + ", + ); + let sub_folder = paths::root().join("foo/.cargo"); + write_config_at( + sub_folder.join("config.toml"), + " + [alias] + sub-example = [\"sub\", \"example\"] + [build] + rustflags = [\"--flag-directory\"] + ", + ); + sub_folder +} + +#[cargo_test] +fn get_toml() { + // Notes: + // - The "extra-table" is shown without a warning. I'm not sure how that + // should be handled, since displaying warnings could cause problems + // with ingesting the output. + // - Environment variables aren't loaded. :( + let sub_folder = common_setup(); + cargo_process("config get -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_ALIAS_BAR", "cat dog") + .env("CARGO_BUILD_JOBS", "100") + // The weird forward slash in the linux line is due to testsuite normalization. + .with_stdout_data(str![[r#" +alias.foo = "abc --xyz" +alias.sub-example = ["sub", "example"] +build.jobs = 99 +build.rustflags = ["--flag-global", "--flag-directory"] +extra-table.somekey = "somevalue" +profile.dev.opt-level = 3 +profile.dev.package.foo.opt-level = 1 +target.'cfg(target_os = "linux")'.runner = "runme" +# The following environment variables may affect the loaded values. +# CARGO_ALIAS_BAR=[..]cat dog[..] +# CARGO_BUILD_JOBS=100 +# CARGO_HOME=[ROOT]/home/.cargo + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + // Env keys work if they are specific. + cargo_process("config get build.jobs -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_BUILD_JOBS", "100") + .with_stdout_data(str![[r#" +build.jobs = 100 + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + // Array value. + cargo_process("config get build.rustflags -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stdout_data(str![[r#" +build.rustflags = ["--flag-global", "--flag-directory"] + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + // Sub-table + cargo_process("config get profile -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stdout_data(str![[r#" +profile.dev.opt-level = 3 +profile.dev.package.foo.opt-level = 1 + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + // Specific profile entry. + cargo_process("config get profile.dev.opt-level -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stdout_data(str![[r#" +profile.dev.opt-level = 3 + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + // A key that isn't set. + cargo_process("config get build.rustc -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_status(101) + .with_stdout_data(str![[r#""#]]) + .with_stderr_data(str![[r#" +[ERROR] config value `build.rustc` is not set + +"#]]) + .run(); + + // A key that is not part of Cargo's config schema. + cargo_process("config get not.set -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_status(101) + .with_stdout_data(str![[r#""#]]) + .with_stderr_data(str![[r#" +[ERROR] config value `not.set` is not set + +"#]]) + .run(); +} + +#[cargo_test] +fn get_json() { + let sub_folder = common_setup(); + cargo_process("config get --format=json -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_ALIAS_BAR", "cat dog") + .env("CARGO_BUILD_JOBS", "100") + .with_stdout_data( + r#" +{ + "alias": { + "foo": "abc --xyz", + "sub-example": [ + "sub", + "example" + ] + }, + "build": { + "jobs": 99, + "rustflags": [ + "--flag-global", + "--flag-directory" + ] + }, + "extra-table": { + "somekey": "somevalue" + }, + "profile": { + "dev": { + "opt-level": 3, + "package": { + "foo": { + "opt-level": 1 + } + } + } + }, + "target": { + "cfg(target_os = \"linux\")": { + "runner": "runme" + } + } +} + +"# + .is_json(), + ) + .with_stderr_data(str![[r#" +[NOTE] The following environment variables may affect the loaded values. +CARGO_ALIAS_BAR=[..]cat dog[..] +CARGO_BUILD_JOBS=100 +CARGO_HOME=[ROOT]/home/.cargo + +"#]]) + .run(); + + // json-value is the same for the entire root table + cargo_process("config get --format=json-value -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stdout_data( + r#" +{ + "alias": { + "foo": "abc --xyz", + "sub-example": [ + "sub", + "example" + ] + }, + "build": { + "jobs": 99, + "rustflags": [ + "--flag-global", + "--flag-directory" + ] + }, + "extra-table": { + "somekey": "somevalue" + }, + "profile": { + "dev": { + "opt-level": 3, + "package": { + "foo": { + "opt-level": 1 + } + } + } + }, + "target": { + "cfg(target_os = \"linux\")": { + "runner": "runme" + } + } +} + +"# + .is_json(), + ) + .with_stderr_data(str![[r#" +[NOTE] The following environment variables may affect the loaded values. +CARGO_HOME=[ROOT]/home/.cargo + +"#]]) + .run(); + + cargo_process("config get --format=json build.jobs -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stdout_data(str![[r#" +{"build":{"jobs":99}} + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get --format=json-value build.jobs -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stdout_data(str![[r#" +99 + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); +} + +#[cargo_test] +fn show_origin_toml() { + let sub_folder = common_setup(); + cargo_process("config get --show-origin -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stdout_data(str![[r#" +alias.foo = "abc --xyz" # [ROOT]/home/.cargo/config.toml +alias.sub-example = [ + "sub", # [ROOT]/foo/.cargo/config.toml + "example", # [ROOT]/foo/.cargo/config.toml +] +build.jobs = 99 # [ROOT]/home/.cargo/config.toml +build.rustflags = [ + "--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 +profile.dev.package.foo.opt-level = 1 # [ROOT]/home/.cargo/config.toml +target.'cfg(target_os = "linux")'.runner = "runme" # [ROOT]/home/.cargo/config.toml +# The following environment variables may affect the loaded values. +# CARGO_HOME=[ROOT]/home/.cargo + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get --show-origin build.rustflags -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_BUILD_RUSTFLAGS", "env1 env2") + .with_stdout_data(str![[r#" +build.rustflags = [ + "--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` +] + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); +} + +#[cargo_test] +fn show_origin_toml_cli() { + let sub_folder = common_setup(); + cargo_process("config get --show-origin build.jobs -Zunstable-options --config build.jobs=123") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_BUILD_JOBS", "1") + .with_stdout_data(str![[r#" +build.jobs = 123 # --config cli option + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get --show-origin build.rustflags -Zunstable-options --config") + .arg("build.rustflags=[\"cli1\",\"cli2\"]") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_BUILD_RUSTFLAGS", "env1 env2") + .with_stdout_data(str![[r#" +build.rustflags = [ + "--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` + "cli1", # --config cli option + "cli2", # --config cli option +] + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); +} + +#[cargo_test] +fn show_origin_json() { + let sub_folder = common_setup(); + cargo_process("config get --show-origin --format=json -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `json` format does not support --show-origin, try the `toml` format instead + +"#]]) + .run(); +} + +#[cargo_test] +fn unmerged_toml() { + let sub_folder = common_setup(); + cargo_process("config get --merged=no -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_ALIAS_BAR", "cat dog") + .env("CARGO_BUILD_JOBS", "100") + .with_stdout_data(str![[r#" +# Environment variables +# CARGO=[..] +# CARGO_ALIAS_BAR=[..]cat dog[..] +# CARGO_BUILD_JOBS=100 +# CARGO_HOME=[ROOT]/home/.cargo + +# [ROOT]/foo/.cargo/config.toml +alias.sub-example = ["sub", "example"] +build.rustflags = ["--flag-directory"] + +# [ROOT]/home/.cargo/config.toml +alias.foo = "abc --xyz" +build.jobs = 99 +build.rustflags = ["--flag-global"] +extra-table.somekey = "somevalue" +profile.dev.opt-level = 3 +profile.dev.package.foo.opt-level = 1 +target.'cfg(target_os = "linux")'.runner = "runme" + + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get --merged=no build.rustflags -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_BUILD_RUSTFLAGS", "env1 env2") + .with_stdout_data(str![[r#" +# Environment variables +# CARGO_BUILD_RUSTFLAGS=[..]env1 env2[..] + +# [ROOT]/foo/.cargo/config.toml +build.rustflags = ["--flag-directory"] + +# [ROOT]/home/.cargo/config.toml +build.rustflags = ["--flag-global"] + + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get --merged=no does.not.exist -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_stderr_data(str![[r#""#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get --merged=no build.rustflags.extra -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] expected table for configuration key `build.rustflags`, but found array in [ROOT]/foo/.cargo/config.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn unmerged_toml_cli() { + let sub_folder = common_setup(); + cargo_process("config get --merged=no build.rustflags -Zunstable-options --config") + .arg("build.rustflags=[\"cli1\",\"cli2\"]") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .env("CARGO_BUILD_RUSTFLAGS", "env1 env2") + .with_stdout_data(str![[r#" +# --config cli option +build.rustflags = ["cli1", "cli2"] + +# Environment variables +# CARGO_BUILD_RUSTFLAGS=[..]env1 env2[..] + +# [ROOT]/foo/.cargo/config.toml +build.rustflags = ["--flag-directory"] + +# [ROOT]/home/.cargo/config.toml +build.rustflags = ["--flag-global"] + + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); +} + +#[cargo_test] +fn unmerged_json() { + let sub_folder = common_setup(); + cargo_process("config get --merged=no --format=json -Zunstable-options") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `json` format does not support --merged=no, try the `toml` format instead + +"#]]) + .run(); +} + +#[cargo_test] +fn includes() { + let sub_folder = common_setup(); + fs::write( + sub_folder.join("config.toml"), + " + include = 'other.toml' + [build] + rustflags = [\"--flag-directory\"] + ", + ) + .unwrap(); + fs::write( + sub_folder.join("other.toml"), + " + [build] + rustflags = [\"--flag-other\"] + ", + ) + .unwrap(); + + 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_data(str![[r#" +build.rustflags = ["--flag-global", "--flag-other", "--flag-directory"] + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get build.rustflags --show-origin -Zunstable-options -Zconfig-include") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config", "config-include"]) + .with_stdout_data(str![[r#" +build.rustflags = [ + "--flag-global", # [ROOT]/home/.cargo/config.toml + "--flag-other", # [ROOT]/foo/.cargo/other.toml + "--flag-directory", # [ROOT]/foo/.cargo/config.toml +] + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); + + cargo_process("config get --merged=no -Zunstable-options -Zconfig-include") + .cwd(&sub_folder.parent().unwrap()) + .masquerade_as_nightly_cargo(&["cargo-config", "config-include"]) + .with_stdout_data(str![[r#" +# Environment variables +# CARGO=[..] +# CARGO_HOME=[ROOT]/home/.cargo + +# [ROOT]/foo/.cargo/other.toml +build.rustflags = ["--flag-other"] + +# [ROOT]/foo/.cargo/config.toml +build.rustflags = ["--flag-directory"] +include = "other.toml" + +# [ROOT]/home/.cargo/config.toml +alias.foo = "abc --xyz" +build.jobs = 99 +build.rustflags = ["--flag-global"] +extra-table.somekey = "somevalue" +profile.dev.opt-level = 3 +profile.dev.package.foo.opt-level = 1 +target.'cfg(target_os = "linux")'.runner = "runme" + + +"#]]) + .with_stderr_data(str![[r#""#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/mod.rs new file mode 100644 index 000000000..3f9f6a6df --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("doc") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/stdout.term.svg new file mode 100644 index 000000000..93b7145cb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/help/stdout.term.svg @@ -0,0 +1,134 @@ + + + + + + + Build a package's documentation + + + + Usage: cargo[EXE] doc [OPTIONS] + + + + Options: + + --open Opens the docs in a browser after the operation + + --no-deps Don't build documentation for dependencies + + --document-private-items Document private items + + --message-format <FMT> Error format + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to document + + --workspace Document all packages in the workspace + + --exclude <SPEC> Exclude packages from the build + + --all Alias for --workspace (deprecated) + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + Target Selection: + + --lib Document only this package's library + + --bins Document all binaries + + --bin [<NAME>] Document only the specified binary + + --examples Document all examples + + --example [<NAME>] Document only the specified example + + + + 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 + + -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-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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help doc` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_doc/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_env_config.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_env_config.rs new file mode 100644 index 000000000..5f420d311 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_env_config.rs @@ -0,0 +1,443 @@ +//! Tests for `[env]` config. + +use cargo_test_support::basic_manifest; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{basic_bin_manifest, project}; + +#[cargo_test] +fn env_basic() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + use std::env; + fn main() { + println!( "compile-time:{}", env!("ENV_TEST_1233") ); + println!( "run-time:{}", env::var("ENV_TEST_1233").unwrap()); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + ENV_TEST_1233 = "Hello" + "#, + ) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +compile-time:Hello +run-time:Hello + +"#]]) + .run(); +} + +#[cargo_test] +fn env_invalid() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + fn main() { + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + ENV_TEST_BOOL = false + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `env.ENV_TEST_BOOL` + +Caused by: + error in [ROOT]/foo/.cargo/config.toml: could not load config key `env.ENV_TEST_BOOL` + +Caused by: + invalid type: boolean `false`, expected a string or map + +"#]]) + .run(); +} + +#[cargo_test] +fn env_no_disallowed() { + // Checks for keys that are not allowed in the [env] table. + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/lib.rs", "") + .build(); + + for disallowed in &["CARGO_HOME", "RUSTUP_HOME", "RUSTUP_TOOLCHAIN"] { + p.change_file( + ".cargo/config.toml", + &format!( + r#" + [env] + {disallowed} = "foo" + "# + ), + ); + p.cargo("check") + .with_status(101) + .with_stderr_data(format!( + "\ +[ERROR] setting the `{disallowed}` environment variable \ +is not supported in the `[env]` configuration table +" + )) + .run(); + } +} + +#[cargo_test] +fn env_force() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + use std::env; + fn main() { + println!( "ENV_TEST_FORCED:{}", env!("ENV_TEST_FORCED") ); + println!( "ENV_TEST_UNFORCED:{}", env!("ENV_TEST_UNFORCED") ); + println!( "ENV_TEST_UNFORCED_DEFAULT:{}", env!("ENV_TEST_UNFORCED_DEFAULT") ); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + ENV_TEST_UNFORCED_DEFAULT = "from-config" + ENV_TEST_UNFORCED = { value = "from-config", force = false } + ENV_TEST_FORCED = { value = "from-config", force = true } + "#, + ) + .build(); + + p.cargo("run") + .env("ENV_TEST_FORCED", "from-env") + .env("ENV_TEST_UNFORCED", "from-env") + .env("ENV_TEST_UNFORCED_DEFAULT", "from-env") + .with_stdout_data(str![[r#" +ENV_TEST_FORCED:from-config +ENV_TEST_UNFORCED:from-env +ENV_TEST_UNFORCED_DEFAULT:from-env + +"#]]) + .run(); +} + +#[cargo_test] +fn env_relative() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo2")) + .file( + "src/main.rs", + r#" + use std::env; + use std::path::Path; + fn main() { + println!( "ENV_TEST_REGULAR:{}", env!("ENV_TEST_REGULAR") ); + println!( "ENV_TEST_REGULAR_DEFAULT:{}", env!("ENV_TEST_REGULAR_DEFAULT") ); + println!( "ENV_TEST_RELATIVE:{}", env!("ENV_TEST_RELATIVE") ); + + assert!( Path::new(env!("ENV_TEST_RELATIVE")).is_absolute() ); + assert!( !Path::new(env!("ENV_TEST_REGULAR")).is_absolute() ); + assert!( !Path::new(env!("ENV_TEST_REGULAR_DEFAULT")).is_absolute() ); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + ENV_TEST_REGULAR = { value = "Cargo.toml", relative = false } + ENV_TEST_REGULAR_DEFAULT = "Cargo.toml" + ENV_TEST_RELATIVE = { value = "Cargo.toml", relative = true } + "#, + ) + .build(); + + p.cargo("run").run(); +} + +#[cargo_test] +fn env_no_override() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("unchanged")) + .file( + "src/main.rs", + r#" + use std::env; + fn main() { + println!( "CARGO_PKG_NAME:{}", env!("CARGO_PKG_NAME") ); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + CARGO_PKG_NAME = { value = "from-config", force = true } + "#, + ) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +CARGO_PKG_NAME:unchanged + +"#]]) + .run(); +} + +#[cargo_test] +fn env_applied_to_target_info_discovery_rustc() { + let wrapper = project() + .at("wrapper") + .file("Cargo.toml", &basic_manifest("wrapper", "1.0.0")) + .file( + "src/main.rs", + r#" + fn main() { + let mut cmd = std::env::args().skip(1).collect::>(); + // This will be invoked twice (with `-vV` and with all the `--print`), + // make sure the environment variable exists each time. + let env_test = std::env::var("ENV_TEST").unwrap(); + eprintln!("WRAPPER ENV_TEST:{env_test}"); + let (prog, args) = cmd.split_first().unwrap(); + let status = std::process::Command::new(prog) + .args(args).status().unwrap(); + std::process::exit(status.code().unwrap_or(1)); + } + "#, + ) + .build(); + wrapper.cargo("build").run(); + let wrapper = &wrapper.bin("wrapper"); + + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + fn main() { + eprintln!( "MAIN ENV_TEST:{}", std::env!("ENV_TEST") ); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + ENV_TEST = "from-config" + "#, + ) + .build(); + + p.cargo("run") + .env("RUSTC_WORKSPACE_WRAPPER", wrapper) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +WRAPPER ENV_TEST:from-config +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` +MAIN ENV_TEST:from-config + +"#]]) + .run(); + + // Ensure wrapper also maintains the same overridden priority for envs. + p.cargo("clean").run(); + p.cargo("run") + .env("ENV_TEST", "from-env") + .env("RUSTC_WORKSPACE_WRAPPER", wrapper) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +WRAPPER ENV_TEST:from-env +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` +MAIN ENV_TEST:from-env + +"#]]) + .run(); +} + +#[cargo_test] +fn env_changed_defined_in_config_toml() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + use std::env; + fn main() { + println!( "{}", env!("ENV_TEST") ); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + ENV_TEST = "from-config" + "#, + ) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +from-config + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + + p.cargo("run") + .env("ENV_TEST", "from-env") + .with_stdout_data(str![[r#" +from-env + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + // This identical cargo invocation is to ensure no rebuild happen. + p.cargo("run") + .env("ENV_TEST", "from-env") + .with_stdout_data(str![[r#" +from-env + +"#]]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn forced_env_changed_defined_in_config_toml() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + use std::env; + fn main() { + println!( "{}", env!("ENV_TEST") ); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [env] + ENV_TEST = {value = "from-config", force = true} + "#, + ) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +from-config + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + + p.cargo("run") + .env("ENV_TEST", "from-env") + .with_stdout_data(str![[r#" +from-config + +"#]]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn env_changed_defined_in_config_args() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + use std::env; + fn main() { + println!( "{}", env!("ENV_TEST") ); + } + "#, + ) + .build(); + p.cargo(r#"run --config 'env.ENV_TEST="one"'"#) + .with_stdout_data(str![[r#" +one + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + + p.cargo(r#"run --config 'env.ENV_TEST="two"'"#) + .with_stdout_data(str![[r#" +two + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + // This identical cargo invocation is to ensure no rebuild happen. + p.cargo(r#"run --config 'env.ENV_TEST="two"'"#) + .with_stdout_data(str![[r#" +two + +"#]]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_features.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_features.rs new file mode 100644 index 000000000..d80f5523e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_features.rs @@ -0,0 +1,710 @@ +//! Tests for `cargo-features` definitions. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{project, registry}; + +#[cargo_test] +fn feature_required() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + im-a-teapot = true + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the `im-a-teapot` manifest key is unstable and may not work properly in England + +Caused by: + feature `test-dummy-unstable` is required + + The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]). + Consider adding `cargo-features = ["test-dummy-unstable"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature. + +"#]]) + .run(); + + // Same, but stable. + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the `im-a-teapot` manifest key is unstable and may not work properly in England + +Caused by: + feature `test-dummy-unstable` is required + + The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]). + Consider trying a newer version of Cargo (this may require the nightly release). + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature. + +"#]]) + .run(); +} + +#[cargo_test] +fn feature_required_dependency() { + // The feature has been stabilized by a future version of Cargo, and + // someone published something uses it, but this version of Cargo has not + // yet stabilized it. Don't suggest editing Cargo.toml, since published + // packages shouldn't be edited. + Package::new("bar", "1.0.0") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + im-a-teapot = true + "#, + ) + .file("src/lib.rs", "") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[ERROR] failed to download replaced source registry `crates-io` + +Caused by: + failed to parse manifest at `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/Cargo.toml` + +Caused by: + the `im-a-teapot` manifest key is unstable and may not work properly in England + +Caused by: + feature `test-dummy-unstable` is required + + The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]). + Consider trying a more recent nightly release. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature. + +"#]]) + .run(); + + // Same, but stable. + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to download `bar v1.0.0` + +Caused by: + unable to get packages from source + +Caused by: + failed to download replaced source registry `crates-io` + +Caused by: + failed to parse manifest at `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/Cargo.toml` + +Caused by: + the `im-a-teapot` manifest key is unstable and may not work properly in England + +Caused by: + feature `test-dummy-unstable` is required + + The package requires the Cargo feature called `test-dummy-unstable`, but that feature is not stabilized in this version of Cargo (1.[..]). + Consider trying a newer version of Cargo (this may require the nightly release). + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html for more information about the status of this feature. + +"#]]) + .run(); +} + +#[cargo_test] +fn unknown_feature() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["foo"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + unknown cargo feature `foo` + +"#]]) + .run(); +} + +#[cargo_test] +fn stable_feature_warns() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-stable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] the cargo feature `test-dummy-stable` has been stabilized in the 1.0 release and is no longer necessary to be listed in the manifest + See https://doc.rust-lang.org/cargo/ for more information about using this feature. +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zallow-features is unstable")] +fn allow_features() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + im-a-teapot = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("-Zallow-features=test-dummy-unstable check") + .masquerade_as_nightly_cargo(&["allow-features", "test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("-Zallow-features=test-dummy-unstable,print-im-a-teapot -Zprint-im-a-teapot check") + .masquerade_as_nightly_cargo(&[ + "allow-features", + "test-dummy-unstable", + "print-im-a-teapot", + ]) + .with_stdout_data(str![[r#" +im-a-teapot = true + +"#]]) + .run(); + + p.cargo("-Zallow-features=test-dummy-unstable -Zprint-im-a-teapot check") + .masquerade_as_nightly_cargo(&[ + "allow-features", + "test-dummy-unstable", + "print-im-a-teapot", + ]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the feature `print-im-a-teapot` is not in the list of allowed features: [test-dummy-unstable] + +"#]]) + .run(); + + p.cargo("-Zallow-features= check") + .masquerade_as_nightly_cargo(&["allow-features", "test-dummy-unstable"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the feature `test-dummy-unstable` is not in the list of allowed features: [] + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zallow-features is unstable")] +fn allow_features_to_rustc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file( + "src/lib.rs", + r#" + #![allow(internal_features)] + #![feature(rustc_attrs)] + "#, + ) + .build(); + + p.cargo("-Zallow-features= check") + .masquerade_as_nightly_cargo(&["allow-features"]) + .with_status(101) + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +error[E0725]: the feature `rustc_attrs` is not in the list of allowed features +... +"#]]) + .run(); + + p.cargo("-Zallow-features=rustc_attrs check") + .masquerade_as_nightly_cargo(&["allow-features"]) + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zallow-features is unstable")] +fn allow_features_in_cfg() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + im-a-teapot = true + "#, + ) + .file( + ".cargo/config.toml", + r#" + [unstable] + allow-features = ["test-dummy-unstable", "print-im-a-teapot"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&[ + "allow-features", + "test-dummy-unstable", + "print-im-a-teapot", + ]) + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("-Zprint-im-a-teapot check") + .masquerade_as_nightly_cargo(&[ + "allow-features", + "test-dummy-unstable", + "print-im-a-teapot", + ]) + .with_stdout_data(str![[r#" +im-a-teapot = true + +"#]]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("-Zunstable-options check") + .masquerade_as_nightly_cargo(&["allow-features", "test-dummy-unstable", "print-im-a-teapot"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the feature `unstable-options` is not in the list of allowed features: [print-im-a-teapot, test-dummy-unstable] + +"#]]) + .run(); + + // -Zallow-features overrides .cargo/config.toml + p.cargo("-Zallow-features=test-dummy-unstable -Zprint-im-a-teapot check") + .masquerade_as_nightly_cargo(&[ + "allow-features", + "test-dummy-unstable", + "print-im-a-teapot", + ]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the feature `print-im-a-teapot` is not in the list of allowed features: [test-dummy-unstable] + +"#]]) + .run(); + + p.cargo("-Zallow-features= check") + .masquerade_as_nightly_cargo(&[ + "allow-features", + "test-dummy-unstable", + "print-im-a-teapot", + ]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the feature `test-dummy-unstable` is not in the list of allowed features: [] + +"#]]) + .run(); +} + +#[cargo_test] +fn nightly_feature_requires_nightly() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + im-a-teapot = true + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, but this is the `stable` channel +... +"#]]) + .run(); +} + +#[cargo_test] +fn nightly_feature_requires_nightly_in_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + im-a-teapot = true + "#, + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] b v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `a` as a dependency of package `b v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `a` + +Caused by: + Unable to update [ROOT]/foo/a + +Caused by: + failed to parse manifest at `[ROOT]/foo/a/Cargo.toml` + +Caused by: + the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, but this is the `stable` channel +... +"#]]) + .run(); +} + +#[cargo_test] +fn cant_publish() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + im-a-teapot = true + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the cargo feature `test-dummy-unstable` requires a nightly version of Cargo, but this is the `stable` channel +... + +"#]]) + .run(); +} + +#[cargo_test] +fn z_flags_rejected() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + im-a-teapot = true + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check -Zprint-im-a-teapot") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel +See [..] + +"#]]) + .run(); + + p.cargo("check -Zarg") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unknown `-Z` flag specified: arg + +For available unstable features, see https://doc.rust-lang.org/nightly/cargo/reference/unstable.html +If you intended to use an unstable rustc feature, try setting `RUSTFLAGS="-Zarg"` + +"#]]) + .run(); + + p.cargo("check -Zprint-im-a-teapot") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_stdout_data(str![[r#" +im-a-teapot = true + +"#]]) + .with_stderr_data(str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_allowed() { + let registry = registry::RegistryBuilder::new() + .http_api() + .http_index() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] a v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] a v0.0.1 ([ROOT]/foo) +[COMPILING] a v0.0.1 ([ROOT]/foo/target/package/a-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] a v0.0.1 ([ROOT]/foo) +[UPLOADED] a v0.0.1 to registry `crates-io` +[NOTE] waiting for `a v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] a v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn wrong_position() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + cargo-features = ["test-dummy-unstable"] + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the field `cargo-features` should be set at the top of Cargo.toml before any tables + --> Cargo.toml:6:34 + | +6 | cargo-features = ["test-dummy-unstable"] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn z_stabilized() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check -Z cache-messages") + .masquerade_as_nightly_cargo(&["always_nightly"]) + .with_stderr_data(str![[r#" +[WARNING] flag `-Z cache-messages` has been stabilized in the 1.40 release, and is no longer necessary + Message caching is now always enabled. + +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check -Z offline") + .masquerade_as_nightly_cargo(&["always_nightly"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] flag `-Z offline` has been stabilized in the 1.36 release + Offline mode is now available via the --offline CLI option + + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/mod.rs new file mode 100644 index 000000000..1f341daf5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("fetch") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/stdout.term.svg new file mode 100644 index 000000000..2607f4950 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/help/stdout.term.svg @@ -0,0 +1,74 @@ + + + + + + + Fetch dependencies of a package from the network + + + + Usage: cargo[EXE] fetch [OPTIONS] + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Compilation Options: + + --target [<TRIPLE>] Fetch dependencies for the target triple + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help fetch` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fetch/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/mod.rs new file mode 100644 index 000000000..22b3fdf14 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("fix") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/stdout.term.svg new file mode 100644 index 000000000..1c8609896 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/help/stdout.term.svg @@ -0,0 +1,150 @@ + + + + + + + Automatically fix lint warnings reported by rustc + + + + Usage: cargo[EXE] fix [OPTIONS] + + + + Options: + + --edition Fix in preparation for the next edition + + --edition-idioms Fix warnings to migrate to the idioms of an edition + + --broken-code Fix code even if it already has compiler errors + + --allow-no-vcs Fix code even if a VCS was not detected + + --allow-dirty Fix code even if the working directory is dirty or has staged + + changes + + --allow-staged Fix code even if the working directory has staged changes + + --message-format <FMT> Error format + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package(s) to fix + + --workspace Fix all packages in the workspace + + --exclude <SPEC> Exclude packages from the fixes + + --all Alias for --workspace (deprecated) + + + + Target Selection: + + --lib Fix only this package's library + + --bins Fix all binaries + + --bin [<NAME>] Fix only the specified binary + + --examples Fix all examples + + --example [<NAME>] Fix only the specified example + + --tests Fix all targets that have `test = true` set + + --test [<NAME>] Fix only the specified test target + + --benches Fix all targets that have `bench = true` set + + --bench [<NAME>] Fix only the specified bench target + + --all-targets Fix all targets (default) + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + -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-dir <DIRECTORY> Directory for all generated artifacts + + --timings[=<FMTS>] Timing output formats (unstable) (comma separated): html, json + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help fix` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_fix/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/mod.rs new file mode 100644 index 000000000..c2fbbfa6a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("generate-lockfile") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/stdout.term.svg new file mode 100644 index 000000000..c53b850c1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/help/stdout.term.svg @@ -0,0 +1,70 @@ + + + + + + + Generate the lockfile for a package + + + + Usage: cargo[EXE] generate-lockfile [OPTIONS] + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help generate-lockfile` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_generate_lockfile/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/mod.rs new file mode 100644 index 000000000..5828fcadf --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("git-checkout") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/stdout.term.svg new file mode 100644 index 000000000..63cb2adc8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/help/stdout.term.svg @@ -0,0 +1,25 @@ + + + + + + + The `git-checkout` command has been removed. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_git_checkout/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/mod.rs new file mode 100644 index 000000000..f5db7e12b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("help") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/stdout.term.svg new file mode 100644 index 000000000..61585e290 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/help/stdout.term.svg @@ -0,0 +1,66 @@ + + + + + + + Displays help for a cargo subcommand + + + + Usage: cargo[EXE] help [OPTIONS] [COMMAND] + + + + Arguments: + + [COMMAND] + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_help/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/mod.rs new file mode 100644 index 000000000..dd10058db --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/mod.rs @@ -0,0 +1,53 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "my-package" + version = "0.1.0" + description = "A package for testing" + repository = "https://github.com/hi-rustin/cargo-infromation" + documentation = "https://docs.rs/my-package/0.1.0" + license = "MIT" + edition = "2018" + rust-version = "1.50.0" + keywords = ["foo", "bar", "baz"] + + [features] + default = ["feature1"] + feature1 = [] + feature2 = [] + + [dependencies] + foo = "0.1.0" + bar = "0.2.0" + baz = { version = "0.3.0", optional = true } + + [[bin]] + name = "my_bin" + + [lib] + name = "my_lib" + "#, + ) + .file("src/bin/my_bin.rs", "") + .file("src/lib.rs", "") + .publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stderr.term.svg new file mode 100644 index 000000000..5d324184d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.1.0 (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stdout.term.svg new file mode 100644 index 000000000..d5e381d76 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/basic/stdout.term.svg @@ -0,0 +1,51 @@ + + + + + + + my-package #foo #bar #baz + + A package for testing + + version: 0.1.0 (from registry `dummy-registry`) + + license: MIT + + rust-version: 1.50.0 + + documentation: https://docs.rs/my-package/0.1.0 + + repository: https://github.com/hi-rustin/cargo-infromation + + features: + + +default = [feature1] + + feature1 = [] + + baz = [dep:baz] + + feature2 = [] + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/mod.rs new file mode 100644 index 000000000..303b589a8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.1") + .feature("default", &["feature1", "feature2"]) + .feature("feature1", &[]) + .feature("feature2", &[]) + .publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stderr.term.svg new file mode 100644 index 000000000..62667b6f8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.1.1 (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stdout.term.svg new file mode 100644 index 000000000..c79747b9b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features/stdout.term.svg @@ -0,0 +1,44 @@ + + + + + + + my-package + + version: 0.1.1 (from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + features: + + +default = [feature1, feature2] + + feature1 = [] + + feature2 = [] + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/mod.rs new file mode 100644 index 000000000..49fadef3e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + const MANY_FEATURES_COUNT: usize = 200; + const DEFAULT_FEATURES_COUNT: usize = 100; + + init_registry_without_token(); + let mut test_package = + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package"); + let features = (0..MANY_FEATURES_COUNT) + .map(|i| format!("eyes{i:03}")) + .collect::>(); + for name in &features { + test_package.feature(name.as_str(), &[]); + } + let default_features = features + .iter() + .take(DEFAULT_FEATURES_COUNT) + .map(|s| s.as_str()) + .collect::>(); + test_package.feature("default", &default_features); + test_package.publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("your-face") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stderr.term.svg new file mode 100644 index 000000000..de41e3894 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded your-face v99999.0.0+my-package (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stdout.term.svg new file mode 100644 index 000000000..53f0e5a02 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit/stdout.term.svg @@ -0,0 +1,43 @@ + + + + + + + your-face + + version: 99999.0.0+my-package (from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + features: + + 101 activated features + + 100 deactivated features + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/mod.rs new file mode 100644 index 000000000..95b4dfdb7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + const MANY_FEATURES_COUNT: usize = 200; + const DEFAULT_FEATURES_COUNT: usize = 100; + + init_registry_without_token(); + let mut test_package = + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package"); + let features = (0..MANY_FEATURES_COUNT) + .map(|i| format!("eyes{i:03}")) + .collect::>(); + for name in &features { + test_package.feature(name.as_str(), &[]); + } + let default_features = features + .iter() + .take(DEFAULT_FEATURES_COUNT) + .map(|s| s.as_str()) + .collect::>(); + test_package.feature("default", &default_features); + test_package.publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("your-face") + .arg("--verbose") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stderr.term.svg new file mode 100644 index 000000000..de41e3894 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded your-face v99999.0.0+my-package (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stdout.term.svg new file mode 100644 index 000000000..e16531b32 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_activated_over_limit_verbose/stdout.term.svg @@ -0,0 +1,441 @@ + + + + + + + your-face + + version: 99999.0.0+my-package (from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + features: + + +default = [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] + + 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 = [] + + eyes100 = [] + + eyes101 = [] + + eyes102 = [] + + eyes103 = [] + + eyes104 = [] + + eyes105 = [] + + eyes106 = [] + + eyes107 = [] + + eyes108 = [] + + eyes109 = [] + + eyes110 = [] + + eyes111 = [] + + eyes112 = [] + + eyes113 = [] + + eyes114 = [] + + eyes115 = [] + + eyes116 = [] + + eyes117 = [] + + eyes118 = [] + + eyes119 = [] + + eyes120 = [] + + eyes121 = [] + + eyes122 = [] + + eyes123 = [] + + eyes124 = [] + + eyes125 = [] + + eyes126 = [] + + eyes127 = [] + + eyes128 = [] + + eyes129 = [] + + eyes130 = [] + + eyes131 = [] + + eyes132 = [] + + eyes133 = [] + + eyes134 = [] + + eyes135 = [] + + eyes136 = [] + + eyes137 = [] + + eyes138 = [] + + eyes139 = [] + + eyes140 = [] + + eyes141 = [] + + eyes142 = [] + + eyes143 = [] + + eyes144 = [] + + eyes145 = [] + + eyes146 = [] + + eyes147 = [] + + eyes148 = [] + + eyes149 = [] + + eyes150 = [] + + eyes151 = [] + + eyes152 = [] + + eyes153 = [] + + eyes154 = [] + + eyes155 = [] + + eyes156 = [] + + eyes157 = [] + + eyes158 = [] + + eyes159 = [] + + eyes160 = [] + + eyes161 = [] + + eyes162 = [] + + eyes163 = [] + + eyes164 = [] + + eyes165 = [] + + eyes166 = [] + + eyes167 = [] + + eyes168 = [] + + eyes169 = [] + + eyes170 = [] + + eyes171 = [] + + eyes172 = [] + + eyes173 = [] + + eyes174 = [] + + eyes175 = [] + + eyes176 = [] + + eyes177 = [] + + eyes178 = [] + + eyes179 = [] + + eyes180 = [] + + eyes181 = [] + + eyes182 = [] + + eyes183 = [] + + eyes184 = [] + + eyes185 = [] + + eyes186 = [] + + eyes187 = [] + + eyes188 = [] + + eyes189 = [] + + eyes190 = [] + + eyes191 = [] + + eyes192 = [] + + eyes193 = [] + + eyes194 = [] + + eyes195 = [] + + eyes196 = [] + + eyes197 = [] + + eyes198 = [] + + eyes199 = [] + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/mod.rs new file mode 100644 index 000000000..ad6bfa03c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + const MANY_FEATURES_COUNT: usize = 200; + const DEFAULT_FEATURES_COUNT: usize = 20; + + init_registry_without_token(); + let mut test_package = + cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package"); + let features = (0..MANY_FEATURES_COUNT) + .map(|i| format!("eyes{i:03}")) + .collect::>(); + for name in &features { + test_package.feature(name.as_str(), &[]); + } + let default_features = features + .iter() + .take(DEFAULT_FEATURES_COUNT) + .map(|s| s.as_str()) + .collect::>(); + test_package.feature("default", &default_features); + test_package.publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("your-face") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stderr.term.svg new file mode 100644 index 000000000..de41e3894 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded your-face v99999.0.0+my-package (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stdout.term.svg new file mode 100644 index 000000000..cfadcd506 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/features_deactivated_over_limit/stdout.term.svg @@ -0,0 +1,83 @@ + + + + + + + your-face + + version: 99999.0.0+my-package (from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + features: + + +default = [eyes000, eyes001, eyes002, eyes003, eyes004, eyes005, eyes006, eyes007, eyes008, eyes009, eyes010, eyes011, eyes012, eyes013, eyes014, eyes015, eyes016, eyes017, eyes018, eyes019] + + eyes000 = [] + + eyes001 = [] + + eyes002 = [] + + eyes003 = [] + + eyes004 = [] + + eyes005 = [] + + eyes006 = [] + + eyes007 = [] + + eyes008 = [] + + eyes009 = [] + + eyes010 = [] + + eyes011 = [] + + eyes012 = [] + + eyes013 = [] + + eyes014 = [] + + eyes015 = [] + + eyes016 = [] + + eyes017 = [] + + eyes018 = [] + + eyes019 = [] + + 180 deactivated features + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/mod.rs new file mode 100644 index 000000000..5872aee30 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/mod.rs @@ -0,0 +1,44 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, file, git, project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + let baz = git::new("baz", |project| { + project + .file("Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("src/lib.rs", "") + }); + + let foo = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + baz = {{ git = '{}' }} + "#, + baz.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + let project_root = foo.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg_line("--verbose foo") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(""); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/stdout.term.svg new file mode 100644 index 000000000..ded341482 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/git_dependency/stdout.term.svg @@ -0,0 +1,40 @@ + + + + + + + foo + + version: 0.1.0 (from ./) + + license: unknown + + rust-version: unknown + + dependencies: + + +baz ([ROOTURL]/baz) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/mod.rs new file mode 100644 index 000000000..edaa377d5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/mod.rs @@ -0,0 +1,13 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(""); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/stdout.term.svg new file mode 100644 index 000000000..7bc930914 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/help/stdout.term.svg @@ -0,0 +1,74 @@ + + + + + + + Display information about a package + + + + Usage: cargo[EXE] info [OPTIONS] <SPEC> + + + + Options: + + --index <INDEX> Registry index URL to search packages in + + --registry <REGISTRY> Registry to search packages in + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + <SPEC> Package to inspect + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help info` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/mod.rs new file mode 100644 index 000000000..ab7a355fc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/mod.rs @@ -0,0 +1,39 @@ +mod basic; +mod features; +mod features_activated_over_limit; +mod features_activated_over_limit_verbose; +mod features_deactivated_over_limit; +mod git_dependency; +mod help; +mod not_found; +mod path_dependency; +mod pick_msrv_compatible_package; +mod pick_msrv_compatible_package_within_ws; +mod pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws; +mod specify_empty_version_with_url; +mod specify_version_outside_ws; +mod specify_version_with_url_but_registry_is_not_matched; +mod specify_version_within_ws_and_conflict_with_lockfile; +mod specify_version_within_ws_and_match_with_lockfile; +mod transitive_dependency_within_ws; +mod verbose; +mod with_frozen_outside_ws; +mod with_frozen_within_ws; +mod with_locked_outside_ws; +mod with_locked_within_ws; +mod with_locked_within_ws_and_pick_the_package; +mod with_offline; +mod with_quiet; +mod within_ws; +mod within_ws_and_pick_ws_package; +mod within_ws_with_alternative_registry; +mod within_ws_without_lockfile; +mod without_requiring_registry_auth; + +// Initialize the registry without a token. +// Otherwise, it will try to list owners of the crate and fail. +pub(crate) fn init_registry_without_token() { + let _reg = cargo_test_support::registry::RegistryBuilder::new() + .no_configure_token() + .build(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/mod.rs new file mode 100644 index 000000000..bccfe0345 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("unknown") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/stderr.term.svg new file mode 100644 index 000000000..7ce41f4a4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/not_found/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating `dummy-registry` index + + error: could not find `unknown` in registry `[ROOTURL]/registry` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/mod.rs new file mode 100644 index 000000000..3c0868953 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg_line("--verbose foo") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(""); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/stdout.term.svg new file mode 100644 index 000000000..426c2aa38 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/path_dependency/stdout.term.svg @@ -0,0 +1,40 @@ + + + + + + + foo + + version: 0.0.0 (from ./) + + license: unknown + + rust-version: unknown + + dependencies: + + +crate1 (./crates/crate1) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/mod.rs new file mode 100644 index 000000000..87f9f2aa4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/mod.rs @@ -0,0 +1,24 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.1+my-package") + .rust_version("1.0.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.0+my-package") + .rust_version("1.9876.0") + .publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stderr.term.svg new file mode 100644 index 000000000..51426fe90 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.1.1+my-package (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stdout.term.svg new file mode 100644 index 000000000..51b4f54fd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 0.1.1+my-package (latest 0.2.0+my-package from registry `dummy-registry`) + + license: unknown + + rust-version: 1.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/mod.rs new file mode 100644 index 000000000..b662a8fd5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.0") + .rust_version("1.0.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.1") + .rust_version("1.9876.0") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root.join("crate1"); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stderr.term.svg new file mode 100644 index 000000000..c48053f56 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.2.0 (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stdout.term.svg new file mode 100644 index 000000000..2c521f36a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 0.2.0 (latest 0.2.1 from registry `dummy-registry`) + + license: unknown + + rust-version: 1.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/mod.rs new file mode 100644 index 000000000..0a57bb395 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/mod.rs @@ -0,0 +1,32 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.0").publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.0") + .rust_version("1.0.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.1") + .rust_version("1.70.0") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root.join("crate1"); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stderr.term.svg new file mode 100644 index 000000000..c48053f56 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.2.0 (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stdout.term.svg new file mode 100644 index 000000000..2c521f36a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/pick_msrv_compatible_package_within_ws_and_use_msrv_from_ws/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 0.2.0 (latest 0.2.1 from registry `dummy-registry`) + + license: unknown + + rust-version: 1.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/mod.rs new file mode 100644 index 000000000..ee6c90ec2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{file, registry::RegistryBuilder}; + +#[cargo_test] +fn case() { + let _ = RegistryBuilder::new() + .alternative() + .no_configure_token() + .build(); + cargo_test_support::registry::Package::new("my-package", "99999.0.0-alpha.1+my-package") + .alternative(true) + .publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("https://crates.io") + .arg("--registry=alternative") + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/stderr.term.svg new file mode 100644 index 000000000..9893f1e61 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_empty_version_with_url/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + error: invalid package ID specification: `https://crates.io` + + + + Caused by: + + package name cannot be empty + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/mod.rs new file mode 100644 index 000000000..bfc36dfd7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/mod.rs @@ -0,0 +1,20 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in ["0.1.1+my-package", "0.2.0+my-package", "0.2.3+my-package"] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package@0.2") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stderr.term.svg new file mode 100644 index 000000000..d607725e4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.2.3+my-package (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stdout.term.svg new file mode 100644 index 000000000..31a21fb5e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_outside_ws/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 0.2.3+my-package (from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/mod.rs new file mode 100644 index 000000000..3d460ccf4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{file, registry::RegistryBuilder}; + +#[cargo_test] +fn case() { + let _ = RegistryBuilder::new() + .alternative() + .no_configure_token() + .build(); + cargo_test_support::registry::Package::new("my-package", "99999.0.0-alpha.1+my-package") + .alternative(true) + .publish(); + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("https://crates.io/my-package") + .arg("--registry=alternative") + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/stderr.term.svg new file mode 100644 index 000000000..319478675 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_with_url_but_registry_is_not_matched/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating `alternative` index + + error: could not find `https://crates.io/my-package` in registry `[ROOTURL]/alternative-registry` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/mod.rs new file mode 100644 index 000000000..a433b78e6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package@0.4") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stderr.term.svg new file mode 100644 index 000000000..c7cd67904 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.4.1+my-package (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stdout.term.svg new file mode 100644 index 000000000..78c9f57e0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_conflict_with_lockfile/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 0.4.1+my-package (latest 99999.0.0+my-package from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/mod.rs new file mode 100644 index 000000000..736a99286 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package@0.1") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stderr.term.svg new file mode 100644 index 000000000..0ff9f8766 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.1.1+my-package (registry `dummy-registry`) + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@0.1.1+my-package` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stdout.term.svg new file mode 100644 index 000000000..1a5eeda16 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/specify_version_within_ws_and_match_with_lockfile/stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 0.1.1+my-package (latest 99999.0.0+my-package) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/0.1.1+my-package + + crates.io: https://crates.io/crates/my-package/0.1.1+my-package + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stderr.term.svg new file mode 100644 index 000000000..c5e249c38 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Downloading crates ... + + Downloaded my-package v1.0.0 (registry `dummy-registry`) + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@1.0.0` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stdout.term.svg new file mode 100644 index 000000000..cd2f7e3da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct1-stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 1.0.0 (latest 99.0.0) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/1.0.0 + + crates.io: https://crates.io/crates/my-package/1.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stderr.term.svg new file mode 100644 index 000000000..573babc22 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@2.0.0` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stdout.term.svg new file mode 100644 index 000000000..c6f35ac32 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/direct2-stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 2.0.0 (latest 99.0.0) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/2.0.0 + + crates.io: https://crates.io/crates/my-package/2.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/mod.rs new file mode 100644 index 000000000..345f6944a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/mod.rs @@ -0,0 +1,78 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + // 99.0.0 is unused + for ver in ["1.0.0", "2.0.0", "3.0.0", "99.0.0"] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + // Dep1 depends on 3.0.0, Dep2 depends on 2.0.0, Dep3 depends on 1.0.0 + cargo_test_support::registry::Package::new("dep1", "1.0.0") + .dep("my-package", "1.0.0") + .publish(); + cargo_test_support::registry::Package::new("dep2", "1.0.0") + .dep("my-package", "2.0.0") + .publish(); + cargo_test_support::registry::Package::new("dep3", "1.0.0") + .dep("my-package", "3.0.0") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let transitive1_root = project_root.join("crates/transitive1"); + let transitive2_root = project_root.join("crates/transitive2"); + let direct1_root = project_root.join("crates/direct1"); + let direct2_root = project_root.join("crates/direct2"); + let ws_directory = &project_root; + let transitive1_directory = &transitive1_root; + let transitive2_directory = &transitive2_root; + let direct1_directory = &direct1_root; + let direct2_directory = &direct2_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(ws_directory) + .assert() + .stdout_eq(file!["ws-stdout.term.svg"]) + .stderr_eq(file!["ws-stderr.term.svg"]); + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(transitive1_directory) + .assert() + .stdout_eq(file!["transitive1-stdout.term.svg"]) + .stderr_eq(file!["transitive1-stderr.term.svg"]); + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(transitive2_directory) + .assert() + .stdout_eq(file!["transitive2-stdout.term.svg"]) + .stderr_eq(file!["transitive2-stderr.term.svg"]); + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(direct1_directory) + .assert() + .stdout_eq(file!["direct1-stdout.term.svg"]) + .stderr_eq(file!["direct1-stderr.term.svg"]); + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(direct2_directory) + .assert() + .stdout_eq(file!["direct2-stdout.term.svg"]) + .stderr_eq(file!["direct2-stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stderr.term.svg new file mode 100644 index 000000000..573babc22 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@2.0.0` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stdout.term.svg new file mode 100644 index 000000000..c6f35ac32 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive1-stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 2.0.0 (latest 99.0.0) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/2.0.0 + + crates.io: https://crates.io/crates/my-package/2.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stderr.term.svg new file mode 100644 index 000000000..573babc22 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@2.0.0` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stdout.term.svg new file mode 100644 index 000000000..c6f35ac32 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/transitive2-stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 2.0.0 (latest 99.0.0) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/2.0.0 + + crates.io: https://crates.io/crates/my-package/2.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stderr.term.svg new file mode 100644 index 000000000..0f123992e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v2.0.0 (registry `dummy-registry`) + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@2.0.0` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stdout.term.svg new file mode 100644 index 000000000..c6f35ac32 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/transitive_dependency_within_ws/ws-stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 2.0.0 (latest 99.0.0) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/2.0.0 + + crates.io: https://crates.io/crates/my-package/2.0.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/mod.rs new file mode 100644 index 000000000..2afb5c199 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/mod.rs @@ -0,0 +1,53 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "my-package" + version = "0.1.0" + description = "A package for testing" + repository = "https://github.com/hi-rustin/cargo-infromation" + documentation = "https://docs.rs/my-package/0.1.0" + license = "MIT" + edition = "2018" + rust-version = "1.50.0" + keywords = ["foo", "bar", "baz"] + + [features] + default = ["feature1"] + feature1 = [] + feature2 = [] + + [dependencies] + foo = "0.1.0" + bar = "0.2.0" + baz = { version = "0.3.0", optional = true } + + [[bin]] + name = "my_bin" + + [lib] + name = "my_lib" + "#, + ) + .file("src/bin/my_bin.rs", "") + .file("src/lib.rs", "") + .publish(); + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--verbose") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stderr.term.svg new file mode 100644 index 000000000..5d324184d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.1.0 (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stdout.term.svg new file mode 100644 index 000000000..9b03148d9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/verbose/stdout.term.svg @@ -0,0 +1,59 @@ + + + + + + + my-package #foo #bar #baz + + A package for testing + + version: 0.1.0 (from registry `dummy-registry`) + + license: MIT + + rust-version: 1.50.0 + + documentation: https://docs.rs/my-package/0.1.0 + + repository: https://github.com/hi-rustin/cargo-infromation + + features: + + +default = [feature1] + + feature1 = [] + + baz = [dep:baz] + + feature2 = [] + + dependencies: + + +bar@0.2.0 + + +foo@0.1.0 + + baz@0.3.0 + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/mod.rs new file mode 100644 index 000000000..c04f6934e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--frozen") + .arg("--registry=dummy-registry") + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/stderr.term.svg new file mode 100644 index 000000000..e695bb9fb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_outside_ws/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: the option `--frozen` can only be used within a workspace + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/mod.rs new file mode 100644 index 000000000..3881f64a8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("unknown") + .arg("--frozen") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/stderr.term.svg new file mode 100644 index 000000000..5d329b55a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_frozen_within_ws/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: could not find `unknown` in registry `[ROOTURL]/registry` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/mod.rs new file mode 100644 index 000000000..6678ac7a3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--locked") + .arg("--registry=dummy-registry") + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/stderr.term.svg new file mode 100644 index 000000000..2d9641b8e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_outside_ws/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: the option `--locked` can only be used within a workspace + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/mod.rs new file mode 100644 index 000000000..4f958d75e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("unknown") + .arg("--locked") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/stderr.term.svg new file mode 100644 index 000000000..12b850a28 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Updating `dummy-registry` index + + error: could not find `unknown` in registry `[ROOTURL]/registry` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/mod.rs new file mode 100644 index 000000000..a04d9ec01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--locked") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stderr.term.svg new file mode 100644 index 000000000..094f2f61c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stderr.term.svg @@ -0,0 +1,31 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v99999.0.0+my-package (registry `dummy-registry`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stdout.term.svg new file mode 100644 index 000000000..6024659dc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_locked_within_ws_and_pick_the_package/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 99999.0.0+my-package (from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/mod.rs new file mode 100644 index 000000000..1b0b71610 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--offline") + .arg("--registry=dummy-registry") + .assert() + .failure() + .stdout_eq("") + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/stderr.term.svg new file mode 100644 index 000000000..d811fbcd0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_offline/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: could not find `my-package` in registry `[ROOTURL]/registry` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/mod.rs new file mode 100644 index 000000000..9c5d0cdb9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--quiet") + .arg("--registry=dummy-registry") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(""); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/stdout.term.svg new file mode 100644 index 000000000..6024659dc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/with_quiet/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 99999.0.0+my-package (from registry `dummy-registry`) + + license: unknown + + rust-version: unknown + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/mod.rs new file mode 100644 index 000000000..f057b5821 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + "20.0.0+my-package", + "99999.0.0+my-package", + "99999.0.0-alpha.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stderr.term.svg new file mode 100644 index 000000000..0ff9f8766 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.1.1+my-package (registry `dummy-registry`) + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@0.1.1+my-package` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stdout.term.svg new file mode 100644 index 000000000..1a5eeda16 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws/stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 0.1.1+my-package (latest 99999.0.0+my-package) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/0.1.1+my-package + + crates.io: https://crates.io/crates/my-package/0.1.1+my-package + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/mod.rs new file mode 100644 index 000000000..cc93e23f6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("cargo-list-test-fixture", "0.1.1+my-package") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("cargo-list-test-fixture") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(""); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/stdout.term.svg new file mode 100644 index 000000000..c83baf475 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_and_pick_ws_package/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + cargo-list-test-fixture + + version: 0.2.0 (from ./) + + license: unknown + + rust-version: unknown + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/mod.rs new file mode 100644 index 000000000..21579d681 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, registry::RegistryBuilder, Project}; +use cargo_test_support::{current_dir, file}; + +#[cargo_test] +fn case() { + let _ = RegistryBuilder::new() + .alternative() + .no_configure_token() + .build(); + cargo_test_support::registry::Package::new("my-package", "99999.0.0-alpha.1+my-package") + .alternative(true) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=alternative") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stderr.term.svg new file mode 100644 index 000000000..69ddaf311 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Updating crates.io index + + Updating `alternative` index + + Downloading crates ... + + Downloaded my-package v99999.0.0-alpha.1+my-package (registry `alternative`) + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stdout.term.svg new file mode 100644 index 000000000..30bf52d0c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_with_alternative_registry/stdout.term.svg @@ -0,0 +1,36 @@ + + + + + + + my-package + + version: 99999.0.0-alpha.1+my-package (from registry `alternative`) + + license: unknown + + rust-version: unknown + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/mod.rs new file mode 100644 index 000000000..6236c4495 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/mod.rs @@ -0,0 +1,33 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + for ver in [ + "0.1.1+my-package", + "0.2.0+my-package", + "0.2.3+my-package", + "0.4.1+my-package", + ] { + cargo_test_support::registry::Package::new("my-package", ver).publish(); + } + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stderr.term.svg new file mode 100644 index 000000000..06f138d01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stderr.term.svg @@ -0,0 +1,39 @@ + + + + + + + Updating `dummy-registry` index + + Locking 1 package to latest compatible version + + Adding my-package v0.2.3+my-package (available: v0.4.1+my-package) + + Downloading crates ... + + Downloaded my-package v0.2.3+my-package (registry `dummy-registry`) + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@0.2.3+my-package` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stdout.term.svg new file mode 100644 index 000000000..ff14e68f3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/within_ws_without_lockfile/stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 0.2.3+my-package (latest 0.4.1+my-package) + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/0.2.3+my-package + + crates.io: https://crates.io/crates/my-package/0.2.3+my-package + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/mod.rs new file mode 100644 index 000000000..20cafe523 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::{compare::assert_ui, current_dir, file, Project}; + +use super::init_registry_without_token; + +#[cargo_test] +fn case() { + init_registry_without_token(); + cargo_test_support::registry::Package::new("my-package", "0.1.1+my-package").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("info") + .arg("my-package") + .arg("--registry=dummy-registry") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stderr.term.svg new file mode 100644 index 000000000..0ff9f8766 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stderr.term.svg @@ -0,0 +1,34 @@ + + + + + + + Updating `dummy-registry` index + + Downloading crates ... + + Downloaded my-package v0.1.1+my-package (registry `dummy-registry`) + + note: to see how you depend on my-package, run `cargo tree --invert --package my-package@0.1.1+my-package` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stdout.term.svg new file mode 100644 index 000000000..bc18725ab --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_info/without_requiring_registry_auth/stdout.term.svg @@ -0,0 +1,39 @@ + + + + + + + my-package + + version: 0.1.1+my-package + + license: unknown + + rust-version: unknown + + documentation: https://docs.rs/my-package/0.1.1+my-package + + crates.io: https://crates.io/crates/my-package/0.1.1+my-package + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/in/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/in/mod.rs new file mode 100644 index 000000000..074954f01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/in/mod.rs @@ -0,0 +1,7 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::{command_is_available, paths, Project}; +use std::fs; +use std::process::Command; + +use crate::test_root; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/mod.rs new file mode 100644 index 000000000..06cb1eb44 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); + assert!(project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/auto_git/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/in/src/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/in/src/main.rs new file mode 100644 index 000000000..65fdcf8da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/in/src/main.rs @@ -0,0 +1,4 @@ +fn main() { + println!("Check that our file is not overwritten") +} + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/mod.rs new file mode 100644 index 000000000..d2855639b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --bin --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/in/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/in/main.rs new file mode 100644 index 000000000..65fdcf8da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/in/main.rs @@ -0,0 +1,4 @@ +fn main() { + println!("Check that our file is not overwritten") +} + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/mod.rs new file mode 100644 index 000000000..db152a15e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --bin --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("src").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_explicit_nosrc/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/in/src/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/in/src/main.rs new file mode 100644 index 000000000..65fdcf8da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/in/src/main.rs @@ -0,0 +1,4 @@ +fn main() { + println!("Check that our file is not overwritten") +} + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/mod.rs new file mode 100644 index 000000000..5a9603a5f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/in/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/in/case.rs new file mode 100644 index 000000000..65fdcf8da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/in/case.rs @@ -0,0 +1,4 @@ +fn main() { + println!("Check that our file is not overwritten") +} + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/mod.rs new file mode 100644 index 000000000..018fe73c3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("src").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namenosrc/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/in/src/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/in/src/case.rs new file mode 100644 index 000000000..65fdcf8da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/in/src/case.rs @@ -0,0 +1,4 @@ +fn main() { + println!("Check that our file is not overwritten") +} + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/mod.rs new file mode 100644 index 000000000..219b54534 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("src/main.rs").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_namesrc/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/in/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/in/main.rs new file mode 100644 index 000000000..65fdcf8da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/in/main.rs @@ -0,0 +1,4 @@ +fn main() { + println!("Check that our file is not overwritten") +} + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/mod.rs new file mode 100644 index 000000000..018fe73c3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("src").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/bin_already_exists_implicit_nosrc/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/mod.rs new file mode 100644 index 000000000..81d1c791f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/mod.rs @@ -0,0 +1,19 @@ +use cargo_test_support::file; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + let cwd = paths::root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --bin") + .current_dir(&cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert!(!cwd.join("Cargo.toml").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/stderr.term.svg new file mode 100644 index 000000000..05b47c7d0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/both_lib_and_bin/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: can't specify both lib and binary outputs + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/case.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/case.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/lib.rs new file mode 100644 index 000000000..59760b549 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/in/lib.rs @@ -0,0 +1 @@ +fn f() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/mod.rs new file mode 100644 index 000000000..2b34486bf --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/mod.rs @@ -0,0 +1,19 @@ +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib") + .current_dir(project_root) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/stderr.term.svg new file mode 100644 index 000000000..be8c5675d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/cant_create_library_when_both_binlib_present/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + error: cannot have a package with multiple libraries, found both `case.rs` and `lib.rs` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/lib.rs new file mode 100644 index 000000000..321163744 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/lib.rs @@ -0,0 +1 @@ +fn f() { println!("lib.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/src/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/src/lib.rs new file mode 100644 index 000000000..f71455a1a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/in/src/lib.rs @@ -0,0 +1 @@ +fn f() { println!("src/lib.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/mod.rs new file mode 100644 index 000000000..f1d364258 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs none") + .current_dir(project_root) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("Cargo.toml").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/lib.rs new file mode 100644 index 000000000..321163744 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/lib.rs @@ -0,0 +1 @@ +fn f() { println!("lib.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/src/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/src/lib.rs new file mode 100644 index 000000000..f71455a1a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/out/src/lib.rs @@ -0,0 +1 @@ +fn f() { println!("src/lib.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/stderr.term.svg new file mode 100644 index 000000000..16fa88745 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/confused_by_multiple_lib_files/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: cannot have a package with multiple libraries, found both `src/lib.rs` and `lib.rs` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/case.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/case.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/lib.rs new file mode 100644 index 000000000..59760b549 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/in/lib.rs @@ -0,0 +1 @@ +fn f() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/mod.rs new file mode 100644 index 000000000..d2855639b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --bin --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_both_binlib_present/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/in/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/in/case.rs new file mode 100644 index 000000000..59760b549 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/in/case.rs @@ -0,0 +1 @@ +fn f() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/mod.rs new file mode 100644 index 000000000..d2855639b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --bin --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/stderr.term.svg new file mode 100644 index 000000000..e92d5b16d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_binary_when_instructed_and_has_lib_file/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Creating binary (application) package + + warning: file `case.rs` seems to be a library file + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/in/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/in/case.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/in/case.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/mod.rs new file mode 100644 index 000000000..4e3cb8b70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/stderr.term.svg new file mode 100644 index 000000000..19cfec206 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/creates_library_when_instructed_and_has_bin_file/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + Creating library package + + warning: file `case.rs` seems to be a binary (application) file + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/empty_dir/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/empty_dir/mod.rs new file mode 100644 index 000000000..074954f01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/empty_dir/mod.rs @@ -0,0 +1,7 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::{command_is_available, paths, Project}; +use std::fs; +use std::process::Command; + +use crate::test_root; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/in/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/in/mod.rs new file mode 100644 index 000000000..074954f01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/in/mod.rs @@ -0,0 +1,7 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::{command_is_available, paths, Project}; +use std::fs; +use std::process::Command; + +use crate::test_root; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/mod.rs new file mode 100644 index 000000000..c0d70abe4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs git --bin") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/explicit_bin_with_git/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/in/rustfmt.toml b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/in/rustfmt.toml new file mode 100644 index 000000000..b196eaa2d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/in/rustfmt.toml @@ -0,0 +1 @@ +tab_spaces = 2 diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/mod.rs new file mode 100644 index 000000000..b35ce6093 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{process, Project}; + +#[cargo_test] +fn case() { + // This cannot use `requires_rustfmt` because rustfmt is not available in + // the rust-lang/rust environment. Additionally, if running cargo without + // rustup (but with rustup installed), this test also fails due to HOME + // preventing the proxy from choosing a toolchain. + if let Err(e) = process("rustfmt").arg("-V").exec_with_output() { + eprintln!("skipping test, rustfmt not available:\n{e:?}"); + return; + } + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/formats_source/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/in/.fossil/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/in/.fossil/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/mod.rs new file mode 100644 index 000000000..132ea3eb9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/fossil_autodetect/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/mod.rs new file mode 100644 index 000000000..f0a78ed3d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use std::fs; + +#[cargo_test] +fn case() { + let project_root = &paths::root().join("foo"); + // Need to create `.git` dir manually because it cannot be tracked under a git repo + fs::create_dir_all(project_root.join(".git")).unwrap(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_autodetect/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/in/.gitignore b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/in/.gitignore new file mode 100644 index 000000000..e3a2b0401 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/in/.gitignore @@ -0,0 +1 @@ +**/some.file \ No newline at end of file diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/mod.rs new file mode 100644 index 000000000..013db91ca --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --edition 2015") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/git_ignore_exists_no_conflicting_entries/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/mod.rs new file mode 100644 index 000000000..fd1930fd4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("init") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/stdout.term.svg new file mode 100644 index 000000000..3cc1f244c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/help/stdout.term.svg @@ -0,0 +1,88 @@ + + + + + + + Create a new cargo package in an existing directory + + + + Usage: cargo[EXE] init [OPTIONS] [PATH] + + + + Arguments: + + [PATH] [default: .] + + + + Options: + + --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, 2021, 2024] + + --name <NAME> Set the resulting package name, defaults to the directory name + + --registry <REGISTRY> Registry to use + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help init` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/in/rustfmt.toml b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/in/rustfmt.toml new file mode 100644 index 000000000..b196eaa2d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/in/rustfmt.toml @@ -0,0 +1 @@ +tab_spaces = 2 diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/mod.rs new file mode 100644 index 000000000..d42e5a9e0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --vcs none") + .env("PATH", "") // pretend that `rustfmt` is missing + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/ignores_failure_to_format_source/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/in/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/in/main.rs new file mode 100644 index 000000000..f328e4d9d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/in/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/mod.rs new file mode 100644 index 000000000..7b59af809 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs git") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_bin_with_git/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/in/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/in/lib.rs new file mode 100644 index 000000000..59760b549 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/in/lib.rs @@ -0,0 +1 @@ +fn f() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/mod.rs new file mode 100644 index 000000000..7b59af809 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs git") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inferred_lib_with_git/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/mod.rs new file mode 100644 index 000000000..99dd923c0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("init") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/inherit_workspace_package_table/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/mod.rs new file mode 100644 index 000000000..b6e4100c9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/mod.rs @@ -0,0 +1,21 @@ +use cargo_test_support::file; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use std::fs; + +#[cargo_test] +fn case() { + let foo = &paths::root().join("foo.bar"); + fs::create_dir_all(foo).unwrap(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init") + .current_dir(foo) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert!(!foo.join("Cargo.toml").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/stderr.term.svg new file mode 100644 index 000000000..ed6458264 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/invalid_dir_name/stderr.term.svg @@ -0,0 +1,44 @@ + + + + + + + Creating binary (application) package + + error: invalid character `.` in package name: `foo.bar`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) + + If you need a package name to not match the directory name, consider using --name flag. + + If you need a binary with the name "foo.bar", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/foo.bar.rs` or change the name in Cargo.toml with: + + + + [[bin]] + + name = "foo.bar" + + path = "src/main.rs" + + + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/in/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/in/lib.rs new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/mod.rs new file mode 100644 index 000000000..219b54534 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("src/main.rs").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_nosrc/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/in/src/lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/in/src/lib.rs new file mode 100644 index 000000000..59760b549 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/in/src/lib.rs @@ -0,0 +1 @@ +fn f() {} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/mod.rs new file mode 100644 index 000000000..219b54534 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("src/main.rs").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/lib_already_exists_src/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/in/.hg/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/in/.hg/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/mod.rs new file mode 100644 index 000000000..132ea3eb9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mercurial_autodetect/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mod.rs new file mode 100644 index 000000000..0b397111e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/mod.rs @@ -0,0 +1,45 @@ +//! Tests for the `cargo init` command. + +mod auto_git; +mod bin_already_exists_explicit; +mod bin_already_exists_explicit_nosrc; +mod bin_already_exists_implicit; +mod bin_already_exists_implicit_namenosrc; +mod bin_already_exists_implicit_namesrc; +mod bin_already_exists_implicit_nosrc; +mod both_lib_and_bin; +mod cant_create_library_when_both_binlib_present; +mod confused_by_multiple_lib_files; +mod creates_binary_when_both_binlib_present; +mod creates_binary_when_instructed_and_has_lib_file; +mod creates_library_when_instructed_and_has_bin_file; +mod explicit_bin_with_git; +mod formats_source; +mod fossil_autodetect; +mod git_autodetect; +mod git_ignore_exists_no_conflicting_entries; +mod help; +mod ignores_failure_to_format_source; +mod inferred_bin_with_git; +mod inferred_lib_with_git; +mod inherit_workspace_package_table; +mod invalid_dir_name; +mod lib_already_exists_nosrc; +mod lib_already_exists_src; +mod mercurial_autodetect; +mod multibin_project_name_clash; +#[cfg(not(windows))] +mod no_filename; +#[cfg(unix)] +mod path_contains_separator; +mod pijul_autodetect; +mod reserved_name; +mod simple_bin; +mod simple_git; +mod simple_git_ignore_exists; +mod simple_hg; +mod simple_hg_ignore_exists; +mod simple_lib; +mod unknown_flags; +mod with_argument; +mod workspace_add_member; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/case.rs new file mode 100644 index 000000000..b31221118 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/case.rs @@ -0,0 +1 @@ +fn main() { println!("foo.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/main.rs new file mode 100644 index 000000000..7937627b9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/in/main.rs @@ -0,0 +1 @@ +fn main() { println!("main.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/mod.rs new file mode 100644 index 000000000..7f87da08d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --vcs none") + .current_dir(project_root) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join("Cargo.toml").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/case.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/case.rs new file mode 100644 index 000000000..b31221118 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/case.rs @@ -0,0 +1 @@ +fn main() { println!("foo.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/main.rs new file mode 100644 index 000000000..7937627b9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/out/main.rs @@ -0,0 +1 @@ +fn main() { println!("main.rs"); } diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/stderr.term.svg new file mode 100644 index 000000000..014fe0997 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/multibin_project_name_clash/stderr.term.svg @@ -0,0 +1,33 @@ + + + + + + + error: multiple possible binary sources found: + + main.rs + + case.rs + + cannot automatically generate Cargo.toml as the main target would be ambiguous + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/mod.rs new file mode 100644 index 000000000..92b3bba71 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/mod.rs @@ -0,0 +1,16 @@ +use cargo_test_support::file; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cfg(not(windows))] +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg_line("init /") + .current_dir(paths::root()) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/stderr.term.svg new file mode 100644 index 000000000..c79694fa2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/no_filename/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: cannot auto-detect package name from path "/" ; use --name to override + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/in/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/in/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/mod.rs new file mode 100644 index 000000000..ad361e103 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/mod.rs @@ -0,0 +1,27 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{t, Project}; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root().join("test:ing"); + + if !project_root.exists() { + t!(std::fs::create_dir(&project_root)); + } + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --bin --vcs none --edition 2015 --name testing") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".gitignore").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/stderr.term.svg new file mode 100644 index 000000000..53e9c0b00 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/path_contains_separator/stderr.term.svg @@ -0,0 +1,35 @@ + + + + + + + Creating binary (application) package + + warning: the path `[ROOT]/case/test:ing/.` contains invalid PATH characters (usually `:`, `;`, or `"`) + + It is recommended to use a different name to avoid problems. + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/in/.pijul/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/in/.pijul/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/mod.rs new file mode 100644 index 000000000..132ea3eb9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/pijul_autodetect/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/mod.rs new file mode 100644 index 000000000..1c06c9401 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/mod.rs @@ -0,0 +1,22 @@ +use std::fs; + +use cargo_test_support::file; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + let project_root = &paths::root().join("test"); + fs::create_dir_all(project_root).unwrap(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init") + .current_dir(project_root) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert!(!project_root.join("Cargo.toml").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/stderr.term.svg new file mode 100644 index 000000000..786e8fdf6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/reserved_name/stderr.term.svg @@ -0,0 +1,44 @@ + + + + + + + Creating binary (application) package + + error: the name `test` cannot be used as a package name, it conflicts with Rust's built-in test library + + If you need a package name to not match the directory name, consider using --name flag. + + If you need a binary with the name "test", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/test.rs` or change the name in Cargo.toml with: + + + + [[bin]] + + name = "test" + + path = "src/main.rs" + + + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/in/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/in/mod.rs new file mode 100644 index 000000000..074954f01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/in/mod.rs @@ -0,0 +1,7 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::{command_is_available, paths, Project}; +use std::fs; +use std::process::Command; + +use crate::test_root; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/mod.rs new file mode 100644 index 000000000..6706742ff --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --bin --vcs none --edition 2015") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".gitignore").is_file()); + + snapbox::cmd::Command::cargo_ui() + .current_dir(project_root) + .arg("build") + .assert() + .success(); + assert!(project.bin("case").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_bin/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/in/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/in/mod.rs new file mode 100644 index 000000000..074954f01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/in/mod.rs @@ -0,0 +1,7 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::{command_is_available, paths, Project}; +use std::fs; +use std::process::Command; + +use crate::test_root; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/mod.rs new file mode 100644 index 000000000..e8af27f46 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --vcs git") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/in/.gitignore b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/in/.gitignore new file mode 100644 index 000000000..d0f753ef7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/in/.gitignore @@ -0,0 +1,2 @@ +/target +**/some.file \ No newline at end of file diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/mod.rs new file mode 100644 index 000000000..c8242fa42 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/mod.rs @@ -0,0 +1,29 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --edition 2015") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(project_root.join(".git").is_dir()); + + snapbox::cmd::Command::cargo_ui() + .current_dir(project_root) + .arg("build") + .assert() + .success(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_git_ignore_exists/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/in/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/in/mod.rs new file mode 100644 index 000000000..074954f01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/in/mod.rs @@ -0,0 +1,7 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::{command_is_available, paths, Project}; +use std::fs; +use std::process::Command; + +use crate::test_root; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/mod.rs new file mode 100644 index 000000000..aa95f8065 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test(requires = "hg")] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --vcs hg") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hg/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hg/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hgignore b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hgignore new file mode 100644 index 000000000..0fc474f27 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/in/.hgignore @@ -0,0 +1 @@ +^/somefile \ No newline at end of file diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/mod.rs new file mode 100644 index 000000000..132ea3eb9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/mod.rs @@ -0,0 +1,23 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".git").is_dir()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_hg_ignore_exists/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/in/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/in/mod.rs new file mode 100644 index 000000000..074954f01 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/in/mod.rs @@ -0,0 +1,7 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::prelude::*; +use cargo_test_support::{command_is_available, paths, Project}; +use std::fs; +use std::process::Command; + +use crate::test_root; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/mod.rs new file mode 100644 index 000000000..9c19bcd52 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --lib --vcs none --edition 2015") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); + assert!(!project_root.join(".gitignore").is_file()); + + snapbox::cmd::Command::cargo_ui() + .current_dir(project_root) + .arg("build") + .assert() + .success(); + assert!(!project.bin("foo").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/stderr.term.svg new file mode 100644 index 000000000..02cb0bb5d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/simple_lib/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/mod.rs new file mode 100644 index 000000000..9df19a755 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/mod.rs @@ -0,0 +1,15 @@ +use cargo_test_support::file; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg_line("init foo --flag") + .current_dir(paths::root()) + .assert() + .code(1) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/stderr.term.svg new file mode 100644 index 000000000..6b3250d8c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/unknown_flags/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + error: unexpected argument '--flag' found + + + + tip: to pass '--flag' as a value, use '-- --flag' + + + + Usage: cargo[EXE] init <PATH> + + + + For more information, try '--help'. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/in/foo/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/in/foo/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/mod.rs new file mode 100644 index 000000000..21862402e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init foo --vcs none") + .current_dir(project_root) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/stderr.term.svg new file mode 100644 index 000000000..9e59a1707 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/with_argument/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/mod.rs new file mode 100644 index 000000000..57d49dcb4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = &project.root(); + + snapbox::cmd::Command::cargo_ui() + .arg_line("init --bin --vcs none") + .current_dir(project_root.join("crates").join("foo")) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/stderr.term.svg new file mode 100644 index 000000000..7c679509b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_init/workspace_add_member/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Creating binary (application) package + + Adding `foo` as member of workspace at `[ROOT]/case` + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/mod.rs new file mode 100644 index 000000000..00dc6f7c4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("install") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/stdout.term.svg new file mode 100644 index 000000000..f750a38a6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/help/stdout.term.svg @@ -0,0 +1,144 @@ + + + + + + + Install a Rust binary + + + + Usage: cargo[EXE] install [OPTIONS] [CRATE[@<VER>]]... + + + + Arguments: + + [CRATE[@<VER>]]... Select the package from the given source + + + + Options: + + --version <VERSION> Specify a version to install + + --index <INDEX> Registry index to install from + + --registry <REGISTRY> Registry to use + + --git <URL> Git URL to install the specified crate from + + --branch <BRANCH> Branch to use when installing from git + + --tag <TAG> Tag to use when installing from git + + --rev <SHA> Specific commit to use when installing from git + + --path <PATH> Filesystem path to local crate to install from + + --root <DIR> Directory to install packages into + + -f, --force Force overwriting existing crates or binaries + + -n, --dry-run Perform all checks without installing (unstable) + + --no-track Do not save tracking information + + --list List all installed packages and their versions + + --message-format <FMT> Error format + + --debug Build in debug mode (with the 'dev' profile) instead of release + + mode + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --ignore-rust-version Ignore `rust-version` specification in packages + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Target Selection: + + --bin [<NAME>] Install only the specified binary + + --bins Install all binaries + + --example [<NAME>] Install only the specified example + + --examples Install all examples + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + --profile <PROFILE-NAME> Install artifacts with the specified profile + + --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 + + + + Run `cargo help install` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_install/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/mod.rs new file mode 100644 index 000000000..6bede7a42 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("locate-project") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/stdout.term.svg new file mode 100644 index 000000000..94fc64e58 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/help/stdout.term.svg @@ -0,0 +1,70 @@ + + + + + + + Print a JSON representation of a Cargo.toml file's location + + + + Usage: cargo[EXE] locate-project [OPTIONS] + + + + Options: + + --workspace Locate Cargo.toml of the workspace root + + --message-format <FMT> Output representation [possible values: json, plain] + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help locate-project` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_locate_project/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/mod.rs new file mode 100644 index 000000000..5416ec105 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("login") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/stdout.term.svg new file mode 100644 index 000000000..a44d055e5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/help/stdout.term.svg @@ -0,0 +1,72 @@ + + + + + + + Log in to a registry. + + + + Usage: cargo[EXE] login [OPTIONS] [-- [args]...] + + + + Arguments: + + [args]... Additional arguments for the credential provider + + + + Options: + + --registry <REGISTRY> Registry to use + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help login` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_login/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/mod.rs new file mode 100644 index 000000000..5bbb986bc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("logout") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/stdout.term.svg new file mode 100644 index 000000000..19f0047f9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/help/stdout.term.svg @@ -0,0 +1,66 @@ + + + + + + + Remove an API token from the registry locally + + + + Usage: cargo[EXE] logout [OPTIONS] + + + + Options: + + --registry <REGISTRY> Registry to use + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help logout` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_logout/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/mod.rs new file mode 100644 index 000000000..7d42b9e62 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("metadata") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/stdout.term.svg new file mode 100644 index 000000000..5cde86fb6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/help/stdout.term.svg @@ -0,0 +1,88 @@ + + + + + + + Output the resolved dependencies of a package, the concrete used versions including overrides, in + + machine-readable format + + + + Usage: cargo[EXE] metadata [OPTIONS] + + + + Options: + + --filter-platform <TRIPLE> Only include resolve dependencies matching the given target-triple + + --no-deps Output information only about the workspace members and don't + + fetch dependencies + + --format-version <VERSION> Format version [possible values: 1] + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help metadata` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_metadata/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/mod.rs new file mode 100644 index 000000000..ddf2ba97a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["bar", "--lib"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/stderr.term.svg new file mode 100644 index 000000000..c54470e14 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_non_workspace/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library `bar` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/stderr.term.svg new file mode 100644 index 000000000..7381994a3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_previous_items/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Creating binary (application) `foo` package + + Adding `foo` as member of workspace at `[ROOT]/case` + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/stderr.term.svg new file mode 100644 index 000000000..7381994a3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_format_sorted/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Creating binary (application) `foo` package + + Adding `foo` as member of workspace at `[ROOT]/case` + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/mod.rs new file mode 100644 index 000000000..aa0e31f72 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/mod.rs @@ -0,0 +1,26 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + let package_path = cwd.join("crates").join("foo"); + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args([package_path]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/stderr.term.svg new file mode 100644 index 000000000..7381994a3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_absolute_package_path/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Creating binary (application) `foo` package + + Adding `foo` as member of workspace at `[ROOT]/case` + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/stderr.term.svg new file mode 100644 index 000000000..7381994a3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_empty_members/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Creating binary (application) `foo` package + + Adding `foo` as member of workspace at `[ROOT]/case` + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/stderr.term.svg new file mode 100644 index 000000000..ab671fb1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_exclude_list/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `foo` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/stderr.term.svg new file mode 100644 index 000000000..ab671fb1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_with_members_glob/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `foo` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/mod.rs new file mode 100644 index 000000000..ddf2ba97a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["bar", "--lib"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/stderr.term.svg new file mode 100644 index 000000000..395e46a58 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/add_members_to_workspace_without_members/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + Creating library `bar` package + + Adding `bar` as member of workspace at `[ROOT]/case` + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/in/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/in/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/mod.rs new file mode 100644 index 000000000..78eeb7ae9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["foo", "--name", ""]) + .current_dir(cwd) + .assert() + .failure() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/out/.keep b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/out/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/stderr.term.svg new file mode 100644 index 000000000..766983fd2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/empty_name/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `` package + + error: package name cannot be empty + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/mod.rs new file mode 100644 index 000000000..55eeac516 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("new") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/stdout.term.svg new file mode 100644 index 000000000..0b9a8c60c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/help/stdout.term.svg @@ -0,0 +1,88 @@ + + + + + + + Create a new cargo package at <path> + + + + Usage: cargo[EXE] new [OPTIONS] <PATH> + + + + Arguments: + + <PATH> + + + + Options: + + --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, 2021, 2024] + + --name <NAME> Set the resulting package name, defaults to the directory name + + --registry <REGISTRY> Registry to use + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help new` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/mod.rs new file mode 100644 index 000000000..d1316c16b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root.join("workspace"); + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["../out-of-workspace", "--lib"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/stderr.term.svg new file mode 100644 index 000000000..7858e42a5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/ignore_current_dir_workspace/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating library `out-of-workspace` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/stderr.term.svg new file mode 100644 index 000000000..ab671fb1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_lints/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `foo` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.term.svg new file mode 100644 index 000000000..ab671fb1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `foo` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs new file mode 100644 index 000000000..8fd9b2592 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo", "--edition", "2021"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.term.svg new file mode 100644 index 000000000..ab671fb1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_edition/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `foo` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs new file mode 100644 index 000000000..d4907c560 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo", "--registry", "foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.term.svg new file mode 100644 index 000000000..ab671fb1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_with_registry/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `foo` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs new file mode 100644 index 000000000..696aeca70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["crates/foo"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.term.svg new file mode 100644 index 000000000..ab671fb1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/inherit_workspace_package_table_without_version/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `foo` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/mod.rs new file mode 100644 index 000000000..b278e95bd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/mod.rs @@ -0,0 +1,17 @@ +mod add_members_to_non_workspace; +mod add_members_to_workspace_format_previous_items; +mod add_members_to_workspace_format_sorted; +mod add_members_to_workspace_with_absolute_package_path; +mod add_members_to_workspace_with_empty_members; +mod add_members_to_workspace_with_exclude_list; +mod add_members_to_workspace_with_members_glob; +mod add_members_to_workspace_without_members; +mod empty_name; +mod help; +mod ignore_current_dir_workspace; +mod inherit_workspace_lints; +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_members; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs new file mode 100644 index 000000000..14434b45c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("new") + .args(["bar"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stderr.term.svg new file mode 100644 index 000000000..69da2f0eb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_new/not_inherit_workspace_package_table_if_not_members/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Creating binary (application) `bar` package + + note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/mod.rs new file mode 100644 index 000000000..8b7669a0c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("owner") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/stdout.term.svg new file mode 100644 index 000000000..10a9819dd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/help/stdout.term.svg @@ -0,0 +1,82 @@ + + + + + + + Manage the owners of a crate on the registry + + + + Usage: cargo[EXE] owner [OPTIONS] [CRATE] + + + + Arguments: + + [CRATE] + + + + 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 URL to modify owners for + + --registry <REGISTRY> Registry to modify owners for + + --token <TOKEN> API token to use when authenticating + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help owner` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_owner/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/mod.rs new file mode 100644 index 000000000..73ff8b7bc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("package") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/stdout.term.svg new file mode 100644 index 000000000..2c41962a1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/help/stdout.term.svg @@ -0,0 +1,112 @@ + + + + + + + Assemble the local package into a distributable tarball + + + + Usage: cargo[EXE] package [OPTIONS] + + + + Options: + + --index <INDEX> Registry index URL to prepare the package for (unstable) + + --registry <REGISTRY> Registry to prepare the package for (unstable) + + -l, --list Print files included in a package without making one + + --no-verify Don't verify the contents by building them + + --no-metadata Ignore warnings about a lack of human-usable metadata + + --allow-dirty Allow dirty working directories to be packaged + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package(s) to assemble + + --workspace Assemble all packages in the workspace + + --exclude <SPEC> Don't assemble specified packages + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + Compilation Options: + + --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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help package` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_package/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/mod.rs new file mode 100644 index 000000000..fb8d622db --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("pkgid") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/stdout.term.svg new file mode 100644 index 000000000..d00cd2644 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/help/stdout.term.svg @@ -0,0 +1,80 @@ + + + + + + + Print a fully qualified package specification + + + + Usage: cargo[EXE] pkgid [OPTIONS] [SPEC] + + + + Arguments: + + [SPEC] + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Argument to get the package ID specifier for + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help pkgid` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_pkgid/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/mod.rs new file mode 100644 index 000000000..ef7802b5c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("publish") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/stdout.term.svg new file mode 100644 index 000000000..40981eb68 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/help/stdout.term.svg @@ -0,0 +1,112 @@ + + + + + + + Upload a package to the registry + + + + Usage: cargo[EXE] publish [OPTIONS] + + + + Options: + + -n, --dry-run Perform all checks without uploading + + --index <INDEX> Registry index URL to upload the package 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 + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package(s) to publish + + --workspace Publish all packages in the workspace (unstable) + + --exclude <SPEC> Don't publish specified packages (unstable) + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + --target [<TRIPLE>] Build for the target triple + + --target-dir <DIRECTORY> Directory for all generated artifacts + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help publish` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_publish/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/mod.rs new file mode 100644 index 000000000..7308a92bc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("read-manifest") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/stdout.term.svg new file mode 100644 index 000000000..6fa71ca6b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/help/stdout.term.svg @@ -0,0 +1,66 @@ + + + + + + + DEPRECATED: Print a JSON representation of a Cargo.toml manifest. + + + + Use `cargo metadata --no-deps` instead. + + + + Usage: cargo[EXE] read-manifest [OPTIONS] + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_read_manifest/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/mod.rs new file mode 100644 index 000000000..bfc3b8a29 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["clippy"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/stderr.term.svg new file mode 100644 index 000000000..8401aa0cb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/avoid_empty_tables/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing clippy from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/mod.rs new file mode 100644 index 000000000..46e7b94fa --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--build", "semver"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/stderr.term.svg new file mode 100644 index 000000000..74f8fd196 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/build/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing semver from build-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/mod.rs new file mode 100644 index 000000000..8a0de7ebe --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--dev", "regex"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/stderr.term.svg new file mode 100644 index 000000000..288a3de64 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dev/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing regex from dev-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/mod.rs new file mode 100644 index 000000000..19278d586 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["semver", "--dry-run"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/stderr.term.svg new file mode 100644 index 000000000..63bbdbbb4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/dry_run/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Removing semver from dependencies + + warning: aborting remove due to dry run + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/mod.rs new file mode 100644 index 000000000..c90110b79 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("serde", "1.0.0").publish(); + cargo_test_support::registry::Package::new("serde_json", "1.0.0") + .dep("serde", "1.0.0") + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + + snapbox::cmd::Command::cargo_ui() + .current_dir(&project_root) + .arg("remove") + .args(["--package", "serde", "serde_derive"]) + .assert() + .code(0) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/stderr.term.svg new file mode 100644 index 000000000..be65cfcd7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_keep_used_patch/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing serde_derive from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/mod.rs new file mode 100644 index 000000000..8e19d068d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/mod.rs @@ -0,0 +1,81 @@ +use cargo_test_support::basic_manifest; +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::git; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + + let git_project1 = git::new("bar1", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + }) + .url(); + + let git_project2 = git::new("bar2", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + }) + .url(); + + let git_project3 = git::new("bar3", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + }) + .url(); + + let in_project = project() + .file( + "Cargo.toml", + &format!( + "[workspace]\n\ + members = [ \"my-member\" ]\n\ + \n\ + [package]\n\ + name = \"my-project\"\n\ + version = \"0.1.0\"\n\ + edition = \"2015\"\n\ + \n\ + [dependencies]\n\ + bar = {{ git = \"{git_project1}\" }}\n\ + \n\ + [patch.\"{git_project1}\"]\n\ + bar = {{ git = \"{git_project3}\" }}\n\ + \n\ + [patch.crates-io]\n\ + bar = {{ git = \"{git_project2}\" }}\n", + ), + ) + .file("src/lib.rs", "") + .file( + "my-member/Cargo.toml", + "[package]\n\ + name = \"my-member\"\n\ + version = \"0.1.0\"\n\ + \n\ + [dependencies]\n\ + bar = \"0.1.0\"\n", + ) + .file("my-member/src/lib.rs", "") + .build(); + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["bar"]) + .current_dir(&in_project.root()) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &in_project.root()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/stderr.term.svg new file mode 100644 index 000000000..154f095e9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_patch/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing bar from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/mod.rs new file mode 100644 index 000000000..1f6f963ae --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.2.3+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_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_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/stderr.term.svg new file mode 100644 index 000000000..ffefd89a7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_profile/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing toml from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/mod.rs new file mode 100644 index 000000000..f2a3cbae1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.2.3+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--package", "my-package", "toml"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/stderr.term.svg new file mode 100644 index 000000000..ffefd89a7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/gc_replace/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing toml from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/mod.rs new file mode 100644 index 000000000..4cad3dda3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/stdout.term.svg new file mode 100644 index 000000000..0a4cfb8db --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/help/stdout.term.svg @@ -0,0 +1,92 @@ + + + + + + + Remove dependencies from a Cargo.toml manifest file + + + + Usage: cargo[EXE] remove [OPTIONS] <DEP_ID>... + + + + Arguments: + + <DEP_ID>... Dependencies to be removed + + + + Options: + + -n, --dry-run Don't actually write the manifest + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Section: + + --dev Remove from dev-dependencies + + --build Remove from build-dependencies + + --target <TARGET> Remove from target-dependencies + + + + Package Selection: + + -p, --package [<SPEC>] Package to remove from + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help remove` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/mod.rs new file mode 100644 index 000000000..28ba8ea36 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["foo", "--flag"]) + .current_dir(cwd) + .assert() + .code(1) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/stderr.term.svg new file mode 100644 index 000000000..ad026d69a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_arg/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + error: unexpected argument '--flag' found + + + + tip: to pass '--flag' as a value, use '-- --flag' + + + + Usage: cargo[EXE] remove <DEP_ID>... + + + + For more information, try '--help'. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/mod.rs new file mode 100644 index 000000000..40da29842 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("invalid-dependency-name", "0.6.2+my-package") + .publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["invalid_dependency_name"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/stderr.term.svg new file mode 100644 index 000000000..5eecfe5e7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_dep/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Removing invalid_dependency_name from dependencies + + error: the dependency `invalid_dependency_name` could not be found in `dependencies`; dependency `invalid-dependency-name` exists + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/mod.rs new file mode 100644 index 000000000..a349d20ad --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("dbus", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("ncurses", "20.0.0+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt", "--package", "dep-c"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/stderr.term.svg new file mode 100644 index 000000000..8123f8668 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + error: package(s) `dep-c` not found in workspace `[ROOT]/case` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/mod.rs new file mode 100644 index 000000000..137a71c0b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("dbus", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("ncurses", "20.0.0+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/stderr.term.svg new file mode 100644 index 000000000..ea4a500c5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_package_multiple/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + error: `cargo remove` could not determine which package to modify. Use the `--package` option to specify a package. + + available packages: dep-a, dep-b + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/mod.rs new file mode 100644 index 000000000..26a9c12db --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--build", "docopt"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/stderr.term.svg new file mode 100644 index 000000000..0166b18c2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Removing docopt from build-dependencies + + error: the dependency `docopt` could not be found in `build-dependencies`; it is present in `dependencies` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/mod.rs new file mode 100644 index 000000000..a61b3b47b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--dev", "semver", "regex"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/stderr.term.svg new file mode 100644 index 000000000..2f08d61b4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_section_dep/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Removing semver from dev-dependencies + + error: the dependency `semver` could not be found in `dev-dependencies`; it is present in `dependencies` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/mod.rs new file mode 100644 index 000000000..c4f41d19e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("dbus", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("ncurses", "20.0.0+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--target", "powerpc-unknown-linux-gnu", "dbus"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/stderr.term.svg new file mode 100644 index 000000000..e1290e530 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Removing dbus from dependencies for target `powerpc-unknown-linux-gnu` + + error: the dependency `dbus` could not be found in `target.powerpc-unknown-linux-gnu.dependencies`; it is present in `target.wasm32-unknown-unknown.dependencies` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/mod.rs new file mode 100644 index 000000000..2286e56ec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("dbus", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("ncurses", "20.0.0+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--target", "wasm32-unknown-unknown", "toml"]) + .current_dir(cwd) + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/stderr.term.svg new file mode 100644 index 000000000..93230d4f6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/invalid_target_dep/stderr.term.svg @@ -0,0 +1,30 @@ + + + + + + + Removing toml from dependencies for target `wasm32-unknown-unknown` + + error: the dependency `toml` could not be found in `target.wasm32-unknown-unknown.dependencies`; it is present in `dependencies` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/mod.rs new file mode 100644 index 000000000..6e287f223 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/mod.rs @@ -0,0 +1,28 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/stderr.term.svg new file mode 100644 index 000000000..51bcb0f99 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/last_dep/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing docopt from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/mod.rs new file mode 100644 index 000000000..3510ece4b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/mod.rs @@ -0,0 +1,37 @@ +mod avoid_empty_tables; +mod build; +mod dev; +mod dry_run; +mod gc_keep_used_patch; +mod gc_patch; +mod gc_profile; +mod gc_replace; +mod help; +mod invalid_arg; +mod invalid_dep; +mod invalid_package; +mod invalid_package_multiple; +mod invalid_section; +mod invalid_section_dep; +mod invalid_target; +mod invalid_target_dep; +mod last_dep; +mod multiple_deps; +mod multiple_dev; +mod no_arg; +mod offline; +mod optional_dep_feature; +mod optional_dep_feature_formatting; +mod optional_feature; +mod package; +mod remove_basic; +mod script; +mod script_last; +mod skip_gc_glob_profile; +mod target; +mod target_build; +mod target_dev; +mod update_lock_file; +mod workspace; +mod workspace_non_virtual; +mod workspace_preserved; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/mod.rs new file mode 100644 index 000000000..5fc96eb49 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt", "semver"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/stderr.term.svg new file mode 100644 index 000000000..475ef4293 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_deps/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Removing docopt from dependencies + + Removing semver from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/mod.rs new file mode 100644 index 000000000..e1594650f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--dev", "regex", "serde"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/stderr.term.svg new file mode 100644 index 000000000..b385a9cef --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/multiple_dev/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Removing regex from dev-dependencies + + Removing serde from dev-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/mod.rs new file mode 100644 index 000000000..70619f2dc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/mod.rs @@ -0,0 +1,37 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .current_dir(cwd) + .assert() + .code(1) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/stderr.term.svg new file mode 100644 index 000000000..d4e40e351 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/no_arg/stderr.term.svg @@ -0,0 +1,39 @@ + + + + + + + error: the following required arguments were not provided: + + <DEP_ID>... + + + + Usage: cargo[EXE] remove <DEP_ID>... + + + + For more information, try '--help'. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/mod.rs new file mode 100644 index 000000000..48b3fc919 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/mod.rs @@ -0,0 +1,45 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + // run the metadata command to populate the cache + snapbox::cmd::Command::cargo_ui() + .arg("metadata") + .current_dir(cwd) + .assert() + .success(); + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt", "--offline"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/stderr.term.svg new file mode 100644 index 000000000..51bcb0f99 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/offline/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing docopt from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/mod.rs new file mode 100644 index 000000000..493a60b5b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--dev", "serde"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/stderr.term.svg new file mode 100644 index 000000000..725449dd6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing serde from dev-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/mod.rs new file mode 100644 index 000000000..21b758ceb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt", "toml"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/stderr.term.svg new file mode 100644 index 000000000..d3aeb2410 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_dep_feature_formatting/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + Removing docopt from dependencies + + Removing toml from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/mod.rs new file mode 100644 index 000000000..30f3e337c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["semver"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/stderr.term.svg new file mode 100644 index 000000000..7ad84cb89 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/optional_feature/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing semver from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/mod.rs new file mode 100644 index 000000000..e3f26e7a5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("dbus", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("ncurses", "20.0.0+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt", "--package", "dep-a"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/stderr.term.svg new file mode 100644 index 000000000..51bcb0f99 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/package/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing docopt from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/mod.rs new file mode 100644 index 000000000..a1aebd4a8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["docopt"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/stderr.term.svg new file mode 100644 index 000000000..51bcb0f99 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/remove_basic/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing docopt from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/in/cargo-remove-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/in/cargo-remove-test-fixture.rs new file mode 100644 index 000000000..99662ce11 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/in/cargo-remove-test-fixture.rs @@ -0,0 +1,23 @@ +--- +edition = "2015" + +[build-dependencies] +semver = "0.1.0" + +[dependencies] +docopt = "0.6" +rustc-serialize = "0.4" +semver = "0.1" +toml = "0.1" +clippy = "0.4" + +[dev-dependencies] +regex = "0.1.1" +serde = "1.0.90" + +[features] +std = ["serde/std", "semver/std"] +--- + +fn main() { +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/mod.rs new file mode 100644 index 000000000..03207eb26 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["script"]) + .arg("-Zscript") + .arg("remove") + .arg_line("--manifest-path cargo-remove-test-fixture.rs docopt") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/out/cargo-remove-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/out/cargo-remove-test-fixture.rs new file mode 100644 index 000000000..16bdb6028 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/out/cargo-remove-test-fixture.rs @@ -0,0 +1,22 @@ +--- +edition = "2015" + +[build-dependencies] +semver = "0.1.0" + +[dependencies] +rustc-serialize = "0.4" +semver = "0.1" +toml = "0.1" +clippy = "0.4" + +[dev-dependencies] +regex = "0.1.1" +serde = "1.0.90" + +[features] +std = ["serde/std", "semver/std"] +--- + +fn main() { +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/stderr.term.svg new file mode 100644 index 000000000..6e54530df --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + warning: `package.edition` is unspecified, defaulting to `[..]` + + Removing docopt from dependencies + + warning: `package.edition` is unspecified, defaulting to `[..]` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/in/cargo-remove-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/in/cargo-remove-test-fixture.rs new file mode 100644 index 000000000..679504783 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/in/cargo-remove-test-fixture.rs @@ -0,0 +1,7 @@ +--- +[dependencies] +docopt = "0.6" +--- + +fn main() { +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/mod.rs new file mode 100644 index 000000000..1b7ec0403 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/mod.rs @@ -0,0 +1,30 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["script"]) + .arg("-Zscript") + .arg("remove") + .arg_line("--manifest-path cargo-remove-test-fixture.rs docopt") + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/out/cargo-remove-test-fixture.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/out/cargo-remove-test-fixture.rs new file mode 100644 index 000000000..f299193f9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/out/cargo-remove-test-fixture.rs @@ -0,0 +1,6 @@ +--- + +--- + +fn main() { +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/stderr.term.svg new file mode 100644 index 000000000..6e54530df --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/script_last/stderr.term.svg @@ -0,0 +1,32 @@ + + + + + + + warning: `package.edition` is unspecified, defaulting to `[..]` + + Removing docopt from dependencies + + warning: `package.edition` is unspecified, defaulting to `[..]` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs new file mode 100644 index 000000000..025b031c3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/mod.rs @@ -0,0 +1,28 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +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(current_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_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.term.svg new file mode 100644 index 000000000..ffefd89a7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/skip_gc_glob_profile/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing toml from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/mod.rs new file mode 100644 index 000000000..1f4d176eb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("dbus", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("ncurses", "20.0.0+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--build", "--target", "wasm32-unknown-unknown", "semver"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/stderr.term.svg new file mode 100644 index 000000000..c795f2c3d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_build/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing semver from build-dependencies for target `wasm32-unknown-unknown` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/mod.rs new file mode 100644 index 000000000..168e5ef6c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/mod.rs @@ -0,0 +1,40 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("dbus", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("ncurses", "20.0.0+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--dev", "--target", "wasm32-unknown-unknown", "ncurses"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/stderr.term.svg new file mode 100644 index 000000000..a39f69193 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/target_dev/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing ncurses from dev-dependencies for target `wasm32-unknown-unknown` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/mod.rs new file mode 100644 index 000000000..b5aa3b96b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.1+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["rustc-serialize"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/stderr.term.svg new file mode 100644 index 000000000..ac8298f87 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/update_lock_file/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing rustc-serialize from dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/mod.rs new file mode 100644 index 000000000..4d4610fdb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--package", "my-package", "--build", "semver"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/stderr.term.svg new file mode 100644 index 000000000..74f8fd196 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing semver from build-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/mod.rs new file mode 100644 index 000000000..4d4610fdb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--package", "my-package", "--build", "semver"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/stderr.term.svg new file mode 100644 index 000000000..74f8fd196 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_non_virtual/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing semver from build-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/mod.rs new file mode 100644 index 000000000..4d4610fdb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/mod.rs @@ -0,0 +1,38 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + cargo_test_support::registry::init(); + cargo_test_support::registry::Package::new("clippy", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("docopt", "0.6.2+my-package").publish(); + cargo_test_support::registry::Package::new("regex", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("rustc-serialize", "0.4.0+my-package").publish(); + cargo_test_support::registry::Package::new("toml", "0.1.1+my-package").publish(); + cargo_test_support::registry::Package::new("semver", "0.1.1") + .feature("std", &[]) + .publish(); + cargo_test_support::registry::Package::new("serde", "1.0.90") + .feature("std", &[]) + .publish(); + + let project = Project::from_template(current_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["--package", "my-package", "--build", "semver"]) + .current_dir(cwd) + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); + + assert_ui().subset_matches(current_dir!().join("out"), &project_root); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/stderr.term.svg new file mode 100644 index 000000000..74f8fd196 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_remove/workspace_preserved/stderr.term.svg @@ -0,0 +1,27 @@ + + + + + + + Removing semver from build-dependencies + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/mod.rs new file mode 100644 index 000000000..c05e9e337 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("report") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/stdout.term.svg new file mode 100644 index 000000000..e63f6c624 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/help/stdout.term.svg @@ -0,0 +1,70 @@ + + + + + + + Generate and display various kinds of reports + + + + Usage: cargo[EXE] report [OPTIONS] <COMMAND> + + + + Commands: + + future-incompatibilities Reports any crates which will eventually stop compiling + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help report` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_report/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/mod.rs new file mode 100644 index 000000000..212ed276c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("run") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/stdout.term.svg new file mode 100644 index 000000000..d17ad3e4b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/help/stdout.term.svg @@ -0,0 +1,122 @@ + + + + + + + Run a binary or example of the local package + + + + Usage: cargo[EXE] run [OPTIONS] [ARGS]... + + + + Arguments: + + [ARGS]... Arguments for the binary or example to run + + + + Options: + + --message-format <FMT> Error format + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package with the target to run + + + + Target Selection: + + --bin [<NAME>] Name of the bin target to run + + --example [<NAME>] Name of the example target to run + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + -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-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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help run` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_run/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/mod.rs new file mode 100644 index 000000000..87b66e825 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("rustc") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/stdout.term.svg new file mode 100644 index 000000000..9d77fd23e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/help/stdout.term.svg @@ -0,0 +1,144 @@ + + + + + + + Compile a package, and pass extra options to the compiler + + + + Usage: cargo[EXE] rustc [OPTIONS] [ARGS]... + + + + Arguments: + + [ARGS]... Extra rustc flags + + + + Options: + + --print <INFO> Output compiler information without compiling + + --crate-type <CRATE-TYPE> Comma separated list of types of crates for the compiler to emit + + --future-incompat-report Outputs a future incompatibility report at the end of the build + + --message-format <FMT> Error format + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to build + + + + Target Selection: + + --lib Build only this package's library + + --bins Build all binaries + + --bin [<NAME>] Build only the specified binary + + --examples Build all examples + + --example [<NAME>] Build only the specified example + + --tests Build all targets that have `test = true` set + + --test [<NAME>] Build only the specified test target + + --benches Build all targets that have `bench = true` set + + --bench [<NAME>] Build only the specified bench target + + --all-targets Build all targets + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + -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-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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help rustc` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustc/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/mod.rs new file mode 100644 index 000000000..a1b2a0193 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("rustdoc") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/stdout.term.svg new file mode 100644 index 000000000..3b8093128 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/help/stdout.term.svg @@ -0,0 +1,142 @@ + + + + + + + Build a package's documentation, using specified custom flags. + + + + Usage: cargo[EXE] rustdoc [OPTIONS] [ARGS]... + + + + Arguments: + + [ARGS]... Extra rustdoc flags + + + + Options: + + --open Opens the docs in a browser after the operation + + --message-format <FMT> Error format + + --output-format <FMT> The output type to write (unstable) [possible values: html, json] + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to document + + + + Target Selection: + + --lib Build only this package's library + + --bins Build all binaries + + --bin [<NAME>] Build only the specified binary + + --examples Build all examples + + --example [<NAME>] Build only the specified example + + --tests Build all targets that have `test = true` set + + --test [<NAME>] Build only the specified test target + + --benches Build all targets that have `bench = true` set + + --bench [<NAME>] Build only the specified bench target + + --all-targets Build all targets + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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 + + -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-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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help rustdoc` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_rustdoc/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/mod.rs new file mode 100644 index 000000000..2b96bd572 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("search") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/stdout.term.svg new file mode 100644 index 000000000..cbad58bcc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/help/stdout.term.svg @@ -0,0 +1,76 @@ + + + + + + + Search packages in the registry. Default registry is crates.io + + + + Usage: cargo[EXE] search [OPTIONS] [QUERY]... + + + + Arguments: + + [QUERY]... + + + + Options: + + --limit <LIMIT> Limit the number of results (default: 10, max: 100) + + --index <INDEX> Registry index URL to search packages in + + --registry <REGISTRY> Registry to search packages in + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help search` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_search/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_targets.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_targets.rs new file mode 100644 index 000000000..beec558d9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_targets.rs @@ -0,0 +1,72 @@ +//! Tests specifically related to target handling (lib, bins, examples, tests, benches). + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn warn_unmatched_target_filters() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + test = false + bench = false + "#, + ) + .file("src/lib.rs", r#"fn main() {}"#) + .build(); + + p.cargo("check --tests --bins --examples --benches") + .with_stderr_data(str![[r#" +[WARNING] target filters `bins`, `tests`, `examples`, `benches` specified, but no targets matched; this is a no-op +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn reserved_windows_target_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [[bin]] + name = "con" + path = "src/main.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + if cfg!(windows) { + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] binary target `con` is a reserved Windows filename, this target will not work on Windows platforms +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + } else { + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/mod.rs new file mode 100644 index 000000000..a643dfdbe --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("test") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/stdout.term.svg new file mode 100644 index 000000000..a3bd4b09c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/help/stdout.term.svg @@ -0,0 +1,154 @@ + + + + + + + Execute all unit and integration tests and build examples of a local package + + + + Usage: cargo[EXE] test [OPTIONS] [TESTNAME] [-- [ARGS]...] + + + + Arguments: + + [TESTNAME] If specified, only run tests containing this string in their names + + [ARGS]... Arguments for the test binary + + + + Options: + + --no-run Compile, but don't run tests + + --no-fail-fast Run all tests regardless of failure + + --future-incompat-report Outputs a future incompatibility report at the end of the build + + --message-format <FMT> Error format + + -q, --quiet Display one character per test instead of one line + + -v, --verbose... Use verbose output (-vv very verbose/build.rs output) + + --color <WHEN> Coloring: auto, always, never + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to run tests for + + --workspace Test all packages in the workspace + + --exclude <SPEC> Exclude packages from the test + + --all Alias for --workspace (deprecated) + + + + Target Selection: + + --lib Test only this package's library + + --bins Test all binaries + + --bin [<NAME>] Test only the specified binary + + --examples Test all examples + + --example [<NAME>] Test only the specified example + + --tests Test all targets that have `test = true` set + + --test [<NAME>] Test only the specified test target + + --benches Test all targets that have `bench = true` set + + --bench [<NAME>] Test only the specified bench target + + --all-targets Test all targets (does not include doctests) + + --doc Test only this library's documentation + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --no-default-features Do not activate the `default` feature + + + + 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-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 + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help test` for more detailed information. + + Run `cargo test -- --help` for test binary options. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/mod.rs new file mode 100644 index 000000000..28be9d1a7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/mod.rs @@ -0,0 +1,2 @@ +mod help; +mod no_keep_going; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/mod.rs new file mode 100644 index 000000000..330e3690b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/mod.rs @@ -0,0 +1,22 @@ +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::CargoCommandExt; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_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_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/stderr.term.svg new file mode 100644 index 000000000..b83508dd8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_test/no_keep_going/stderr.term.svg @@ -0,0 +1,42 @@ + + + + + + + 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/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/mod.rs new file mode 100644 index 000000000..6b10af23a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("tree") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/stdout.term.svg new file mode 100644 index 000000000..b06f8f1e5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/help/stdout.term.svg @@ -0,0 +1,118 @@ + + + + + + + Display a tree visualization of a dependency graph + + + + Usage: cargo[EXE] tree [OPTIONS] + + + + Options: + + -e, --edges <KINDS> The kinds of dependencies to display (features, normal, build, dev, + + all, no-normal, no-build, no-dev, no-proc-macro) + + -i, --invert [<SPEC>] Invert the tree direction and focus on the given package + + --prune <SPEC> Prune the given package from the display of the dependency tree + + --depth <DEPTH> Maximum display depth of the dependency tree + + --prefix <PREFIX> Change the prefix (indentation) of how each entry is displayed + + [default: indent] [possible values: depth, indent, none] + + --no-dedupe Do not de-duplicate (repeats all shared dependencies) + + -d, --duplicates Show only dependencies which come in multiple versions (implies -i) + + --charset <CHARSET> Character set to use in output [possible values: utf8, ascii] + + -f, --format <FORMAT> Format string used for printing dependencies [default: {p}] + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to be used as the root of the tree + + --workspace Display the tree for all packages in the workspace + + --exclude <SPEC> Exclude specific workspace members + + + + Feature Selection: + + -F, --features <FEATURES> Space or comma separated list of features to activate + + --all-features Activate all available features + + --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. + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help tree` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_tree/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/mod.rs new file mode 100644 index 000000000..48c84da1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("uninstall") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/stdout.term.svg new file mode 100644 index 000000000..b8a3f8024 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/help/stdout.term.svg @@ -0,0 +1,84 @@ + + + + + + + Remove a Rust binary + + + + Usage: cargo[EXE] uninstall [OPTIONS] [SPEC]... + + + + Arguments: + + [SPEC]... + + + + Options: + + --root <DIR> Directory to uninstall packages from + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -p, --package [<SPEC>] Package to uninstall + + + + Target Selection: + + --bin <NAME> Only uninstall the binary NAME + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help uninstall` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_uninstall/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/mod.rs new file mode 100644 index 000000000..7bc15484c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("update") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/stdout.term.svg new file mode 100644 index 000000000..dd0343c96 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/help/stdout.term.svg @@ -0,0 +1,86 @@ + + + + + + + Update dependencies as recorded in the local lock file + + + + Usage: cargo[EXE] update [OPTIONS] [SPEC]... + + + + Options: + + -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 + + -b, --breaking Update [SPEC] to latest SemVer-breaking version (unstable) + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Package Selection: + + -w, --workspace Only update the workspace packages + + [SPEC]... Package to update + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --ignore-rust-version Ignore `rust-version` specification in packages + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help update` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/mod.rs new file mode 100644 index 000000000..a809d9fe9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/mod.rs @@ -0,0 +1,2 @@ +mod help; +mod toolchain_pkgname; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs new file mode 100644 index 000000000..32055ac0a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/mod.rs @@ -0,0 +1,21 @@ +use cargo_test_support::current_dir; +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::Project; + +#[cargo_test] +fn case() { + let project = Project::from_template(current_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_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/stderr.term.svg new file mode 100644 index 000000000..f765e053a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_update/toolchain_pkgname/stderr.term.svg @@ -0,0 +1,29 @@ + + + + + + + error: invalid character `+` in package name: `+stable` + + Use `cargo +stable update` if you meant to use the `stable` toolchain. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/mod.rs new file mode 100644 index 000000000..ede93a8f8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("vendor") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/stdout.term.svg new file mode 100644 index 000000000..43355fb02 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/help/stdout.term.svg @@ -0,0 +1,82 @@ + + + + + + + Vendor all dependencies for a project locally + + + + Usage: cargo[EXE] vendor [OPTIONS] [path] + + + + Arguments: + + [path] Where to vendor crates (`vendor` by default) + + + + Options: + + --no-delete Don't delete older crates in the vendor directory + + -s, --sync <TOML> Additional `Cargo.toml` to sync and vendor + + --respect-source-config Respect `[source]` config in `.cargo/config` + + --versioned-dirs Always include version in subdir name + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --lockfile-path <PATH> Path to Cargo.lock (unstable) + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help vendor` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_vendor/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/mod.rs new file mode 100644 index 000000000..b5103db60 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("verify-project") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/stdout.term.svg new file mode 100644 index 000000000..130db5c53 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/help/stdout.term.svg @@ -0,0 +1,66 @@ + + + + + + + DEPRECATED: Check correctness of crate manifest. + + + + See https://github.com/rust-lang/cargo/issues/14679. + + + + Usage: cargo[EXE] verify-project [OPTIONS] + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --manifest-path <PATH> Path to Cargo.toml + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_verify_project/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/mod.rs new file mode 100644 index 000000000..a86d204ae --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("version") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/stdout.term.svg new file mode 100644 index 000000000..8d9ddb8e1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/help/stdout.term.svg @@ -0,0 +1,64 @@ + + + + + + + Show version information + + + + Usage: cargo[EXE] version [OPTIONS] + + + + Options: + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help version` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_version/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/mod.rs new file mode 100644 index 000000000..93b5af05e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/mod.rs @@ -0,0 +1,14 @@ +use cargo_test_support::file; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +#[cargo_test] +fn case() { + snapbox::cmd::Command::cargo_ui() + .arg("yank") + .arg("--help") + .assert() + .success() + .stdout_eq(file!["stdout.term.svg"]) + .stderr_eq(str![""]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/stdout.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/stdout.term.svg new file mode 100644 index 000000000..8b006ed25 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/help/stdout.term.svg @@ -0,0 +1,80 @@ + + + + + + + Remove a pushed crate from the index + + + + Usage: cargo[EXE] yank [OPTIONS] [CRATE] + + + + Arguments: + + [CRATE] + + + + 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 URL to yank from + + --registry <REGISTRY> Registry to yank from + + --token <TOKEN> API token to use when authenticating + + -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 + + --config <KEY=VALUE|PATH> Override a configuration value + + -Z <FLAG> Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for + + details + + -h, --help Print help + + + + Manifest Options: + + --locked Assert that `Cargo.lock` will remain unchanged + + --offline Run without accessing the network + + --frozen Equivalent to specifying both --locked and --offline + + + + Run `cargo help yank` for more detailed information. + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/mod.rs new file mode 100644 index 000000000..c0ce11180 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cargo_yank/mod.rs @@ -0,0 +1 @@ +mod help; diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cfg.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cfg.rs new file mode 100644 index 000000000..9b5cd2407 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cfg.rs @@ -0,0 +1,661 @@ +//! Tests for `cfg()` expressions. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::rustc_host; +use cargo_test_support::{basic_manifest, project, str}; + +#[cargo_test] +fn cfg_easy() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(unix)'.dependencies] + b = { path = 'b' } + [target."cfg(windows)".dependencies] + b = { path = 'b' } + "#, + ) + .file("src/lib.rs", "extern crate b;") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + p.cargo("check -v").run(); +} + +#[cargo_test] +fn dont_include() { + let other_family = if cfg!(unix) { "windows" } else { "unix" }; + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg({})'.dependencies] + b = {{ path = 'b' }} + "#, + other_family + ), + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn works_through_the_registry() { + Package::new("baz", "0.1.0").publish(); + Package::new("bar", "0.1.0") + .target_dep("baz", "0.1.0", "cfg(unix)") + .target_dep("baz", "0.1.0", "cfg(windows)") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "#[allow(unused_extern_crates)] extern crate bar;", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`) +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] baz v0.1.0 +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn ignore_version_from_other_platform() { + let this_family = if cfg!(unix) { "unix" } else { "windows" }; + let other_family = if cfg!(unix) { "windows" } else { "unix" }; + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.2.0").publish(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg({})'.dependencies] + bar = "0.1.0" + + [target.'cfg({})'.dependencies] + bar = "0.2.0" + "#, + this_family, other_family + ), + ) + .file( + "src/lib.rs", + "#[allow(unused_extern_crates)] extern crate bar;", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[ADDING] bar v0.1.0 (available: v0.2.0) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_target_spec() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(4)'.dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse `4` as a cfg expression: unexpected character `4` in cfg, expected parens, a comma, an identifier, or a string + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_target_spec2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(bar =)'.dependencies] + baz = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse `bar =` as a cfg expression: expected a string, but cfg expression ended + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_match_ok() { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(unix)'.dependencies] + b = {{ path = 'b' }} + [target.'cfg(target_family = "unix")'.dependencies] + b = {{ path = 'b' }} + [target."cfg(windows)".dependencies] + b = {{ path = 'b' }} + [target.'cfg(target_family = "windows")'.dependencies] + b = {{ path = 'b' }} + [target."cfg(any(windows, unix))".dependencies] + b = {{ path = 'b' }} + + [target.{}.dependencies] + b = {{ path = 'b' }} + "#, + rustc_host() + ), + ) + .file("src/lib.rs", "extern crate b;") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + p.cargo("check -v").run(); +} + +#[cargo_test] +fn any_ok() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target."cfg(any(windows, unix))".dependencies] + b = { path = 'b' } + "#, + ) + .file("src/lib.rs", "extern crate b;") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + p.cargo("check -v").run(); +} + +// https://github.com/rust-lang/cargo/issues/5313 +#[cargo_test] +#[cfg(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"))] +fn cfg_looks_at_rustflags_for_target() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(with_b)'.dependencies] + b = { path = 'b' } + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(with_b)] + extern crate b; + + fn main() { b::foo(); } + "#, + ) + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("check --target x86_64-unknown-linux-gnu") + .env("RUSTFLAGS", "--cfg with_b") + .run(); +} + +#[cargo_test] +fn bad_cfg_discovery() { + // Check error messages when `rustc -v` and `rustc --print=*` parsing fails. + // + // This is a `rustc` replacement which behaves differently based on an + // environment variable. + let p = project() + .at("compiler") + .file("Cargo.toml", &basic_manifest("compiler", "0.1.0")) + .file( + "src/main.rs", + r#" + fn run_rustc() -> String { + let mut cmd = std::process::Command::new("rustc"); + for arg in std::env::args_os().skip(1) { + cmd.arg(arg); + } + String::from_utf8(cmd.output().unwrap().stdout).unwrap() + } + + fn main() { + let mode = std::env::var("FUNKY_MODE").unwrap(); + if mode == "bad-version" { + println!("foo"); + return; + } + if std::env::args_os().any(|a| a == "-vV") { + print!("{}", run_rustc()); + return; + } + if mode == "no-crate-types" { + return; + } + if mode == "bad-crate-type" { + println!("foo"); + return; + } + let output = run_rustc(); + let mut lines = output.lines(); + let sysroot = loop { + let line = lines.next().unwrap(); + if line.contains("___") { + println!("{}", line); + } else { + break line; + } + }; + if mode == "no-sysroot" { + return; + } + println!("{}", sysroot); + + if mode == "no-split-debuginfo" { + return; + } + loop { + let line = lines.next().unwrap(); + if line == "___" { + println!("\n{line}"); + break; + } else { + // As the number split-debuginfo options varies, + // concat them into one line. + print!("{line},"); + } + }; + + if mode != "bad-cfg" { + panic!("unexpected"); + } + println!("123"); + } + "#, + ) + .build(); + p.cargo("build").run(); + let funky_rustc = p.bin("compiler"); + + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check") + .env("RUSTC", &funky_rustc) + .env("FUNKY_MODE", "bad-version") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `rustc -vV` didn't have a line for `host:`, got: +foo + + +"#]]) + .run(); + + p.cargo("check") + .env("RUSTC", &funky_rustc) + .env("FUNKY_MODE", "no-crate-types") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] malformed output when learning about crate-type bin information +command was: `[ROOT]/compiler/target/debug/compiler[..] --crate-name ___ [..]` +(no output received) + +"#]]) + .run(); + + p.cargo("check") + .env("RUSTC", &funky_rustc) + .env("FUNKY_MODE", "no-sysroot") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] output of --print=sysroot missing when learning about target-specific information from rustc +command was: `[ROOT]/compiler/target/debug/compiler[..]--crate-type [..]` + +--- stdout +___[EXE] +lib___.rlib +[..]___.[..] +[..]___.[..] +[..]___.[..] +[..]___.[..] + + +"#]]) + .run(); + + p.cargo("check") + .env("RUSTC", &funky_rustc) + .env("FUNKY_MODE", "no-split-debuginfo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] output of --print=split-debuginfo missing when learning about target-specific information from rustc +command was: `[ROOT]/compiler/target/debug/compiler[..]--crate-type [..]` + +--- stdout +___[EXE] +lib___.rlib +[..]___.[..] +[..]___.[..] +[..]___.[..] +[..]___.[..] +[..] + + +"#]]) + .run(); + + p.cargo("check") + .env("RUSTC", &funky_rustc) + .env("FUNKY_MODE", "bad-cfg") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse the cfg from `rustc --print=cfg`, got: +___[EXE] +lib___.rlib +[..]___.[..] +[..]___.[..] +[..]___.[..] +[..]___.[..] +[..] +[..],[..] +___ +123 + + +Caused by: + failed to parse `123` as a cfg expression: unexpected character `1` in cfg, expected parens, a comma, an identifier, or a string + +"#]]) + .run(); +} + +#[cargo_test] +fn exclusive_dep_kinds() { + // Checks for a bug where the same package with different cfg expressions + // was not being filtered correctly. + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [target.'cfg(abc)'.dependencies] + bar = "1.0" + + [target.'cfg(not(abc))'.build-dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "extern crate bar; fn main() {}") + .build(); + + p.cargo("check").run(); + p.change_file("src/lib.rs", "extern crate bar;"); + p.cargo("check") + .with_status(101) + // can't find crate for `bar` + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +error[E0463]: can't find crate for `bar` +... +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_raw_idents() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [target.'cfg(any(r#true, r#all, r#target_os = "<>"))'.dependencies] + b = { path = "b/" } + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_raw_idents_empty() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [target.'cfg(r#))'.dependencies] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse `r#)` as a cfg expression: unexpected character `)` in cfg, expected parens, a comma, an identifier, or a string + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_raw_idents_not_really() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [target.'cfg(r#11))'.dependencies] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse `r#11)` as a cfg expression: unexpected character `1` in cfg, expected parens, a comma, an identifier, or a string + +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_keywords() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [target.'cfg(any(async, fn, const, return, true))'.dependencies] + b = { path = "b/" } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [target."cfg(any(for, match, extern, crate, false))"] + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] [[ROOT]/foo/Cargo.toml] future-incompatibility: the meaning of `cfg(true)` will change in the future + | Cargo is erroneously allowing `cfg(true)` and `cfg(false)`, but both forms are interpreted as false unless manually overridden with `--cfg`. + | In the future these will be built-in defines that will have the corresponding true/false value. + | It is recommended to avoid using these configs until they are properly supported. + | See for more information. + | + | [HELP] use raw-idents instead: `cfg(r#true)` +[WARNING] [.cargo/config.toml] future-incompatibility: the meaning of `cfg(false)` will change in the future + | Cargo is erroneously allowing `cfg(true)` and `cfg(false)`, but both forms are interpreted as false unless manually overridden with `--cfg`. + | In the future these will be built-in defines that will have the corresponding true/false value. + | It is recommended to avoid using these configs until they are properly supported. + | See for more information. + | + | [HELP] use raw-idents instead: `cfg(r#false)` +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check.rs new file mode 100644 index 000000000..cff23929c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check.rs @@ -0,0 +1,1664 @@ +//! Tests for the `cargo check` command. + +use std::fmt::{self, Write}; + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::install::exe; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::tools; +use cargo_test_support::{basic_bin_manifest, basic_manifest, git, project}; + +#[cargo_test] +fn check_success() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/main.rs", + "extern crate bar; fn main() { ::bar::baz(); }", + ) + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("check").run(); +} + +#[cargo_test] +fn check_fail() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/main.rs", + "extern crate bar; fn main() { ::bar::baz(42); }", + ) + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... +error[E0061]: this function takes 0 arguments but 1 argument was supplied +... +"#]]) + .run(); +} + +#[cargo_test] +fn custom_derive() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/main.rs", + r#" + #[macro_use] + extern crate bar; + + trait B { + fn b(&self); + } + + #[derive(B)] + struct A; + + fn main() { + let a = A; + a.b(); + } + "#, + ) + .build(); + let _bar = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate proc_macro; + + use proc_macro::TokenStream; + + #[proc_macro_derive(B)] + pub fn derive(_input: TokenStream) -> TokenStream { + format!("impl B for A {{ fn b(&self) {{}} }}").parse().unwrap() + } + "#, + ) + .build(); + + foo.cargo("check").run(); +} + +#[cargo_test] +fn check_build() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/main.rs", + "extern crate bar; fn main() { ::bar::baz(); }", + ) + .build(); + + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("check").run(); + foo.cargo("build").run(); +} + +#[cargo_test] +fn build_check() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/main.rs", + "extern crate bar; fn main() { ::bar::baz(); }", + ) + .build(); + + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("build -v").run(); + foo.cargo("check -v").run(); +} + +// Checks that where a project has both a lib and a bin, the lib is only checked +// not built. +#[cargo_test] +fn issue_3418() { + let foo = project() + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .build(); + + foo.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]--emit=[..]metadata [..]` +[RUNNING] `rustc --crate-name foo [..] src/main.rs [..]--emit=[..]metadata [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +// Check on a dylib should have a different metadata hash than build. +#[cargo_test] +fn dylib_check_preserves_build_cache() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [lib] + crate-type = ["dylib"] + + [dependencies] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check").run(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +// test `cargo rustc --profile check` +#[cargo_test] +fn rustc_check() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/main.rs", + "extern crate bar; fn main() { ::bar::baz(); }", + ) + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("rustc --profile check -- --emit=metadata").run(); + + // Verify compatible usage of --profile with --release, issue #7488 + foo.cargo("rustc --profile check --release -- --emit=metadata") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--profile ' cannot be used with '--release' + +Usage: cargo[EXE] rustc --profile [ARGS]... + +For more information, try '--help'. + +"#]]) + .run(); + + foo.cargo("rustc --profile test --release -- --emit=metadata") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--profile ' cannot be used with '--release' + +Usage: cargo[EXE] rustc --profile [ARGS]... + +For more information, try '--help'. + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_check_err() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/main.rs", + "extern crate bar; fn main() { ::bar::qux(); }", + ) + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("rustc --profile check -- --emit=metadata") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +error[E0425]: [..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn check_all() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace] + [dependencies] + b = { path = "b" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("examples/a.rs", "fn main() {}") + .file("tests/a.rs", "") + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/main.rs", "fn main() {}") + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check --workspace -v") + .with_stderr_data( + str![[r#" +[CHECKING] b v0.0.1 ([ROOT]/foo/b) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]` +[RUNNING] `rustc --crate-name foo [..] src/main.rs [..]` +[RUNNING] `rustc --crate-name b [..] b/src/lib.rs [..]` +[RUNNING] `rustc --crate-name b [..] b/src/main.rs [..]` +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn check_all_exclude() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("check --workspace --exclude baz") + .with_stderr_does_not_contain("[CHECKING] baz v0.1.0 [..]") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_all_exclude_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("check --workspace --exclude '*z'") + .with_stderr_does_not_contain("[CHECKING] baz v0.1.0 [..]") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_virtual_all_implied() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check -v") + .with_stderr_data( + str![[r#" +[CHECKING] baz v0.1.0 ([ROOT]/foo/baz) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name baz [..] baz/src/lib.rs [..]` +[RUNNING] `rustc --crate-name bar [..] bar/src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn check_virtual_manifest_one_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("check -p bar") + .with_stderr_does_not_contain("[CHECKING] baz v0.1.0 [..]") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_virtual_manifest_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() { break_the_build(); }") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check -p '*z'") + .with_stderr_does_not_contain("[CHECKING] bar v0.1.0 [..]") + .with_stderr_data(str![[r#" +[CHECKING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn exclude_warns_on_non_existing_package() { + let p = project().file("src/lib.rs", "").build(); + p.cargo("check --workspace --exclude bar") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] excluded package(s) `bar` not found in workspace `[ROOT]/foo` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn targets_selected_default() { + let foo = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "pub fn smth() {}") + .file("examples/example1.rs", "fn main() {}") + .file("tests/test2.rs", "#[test] fn t() {}") + .file("benches/bench3.rs", "") + .build(); + + foo.cargo("check -v") + .with_stderr_contains("[..] --crate-name foo [..] src/lib.rs [..]") + .with_stderr_contains("[..] --crate-name foo [..] src/main.rs [..]") + .with_stderr_does_not_contain("[..] --crate-name example1 [..] examples/example1.rs [..]") + .with_stderr_does_not_contain("[..] --crate-name test2 [..] tests/test2.rs [..]") + .with_stderr_does_not_contain("[..] --crate-name bench3 [..] benches/bench3.rs [..]") + .run(); +} + +#[cargo_test] +fn targets_selected_all() { + let foo = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "pub fn smth() {}") + .file("examples/example1.rs", "fn main() {}") + .file("tests/test2.rs", "#[test] fn t() {}") + .file("benches/bench3.rs", "") + .build(); + + foo.cargo("check --all-targets -v") + .with_stderr_data( + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]` +[RUNNING] `rustc --crate-name foo [..] src/main.rs [..]` +[RUNNING] `rustc --crate-name example1 [..] examples/example1.rs [..]` +[RUNNING] `rustc --crate-name test2 [..] tests/test2.rs [..]` +[RUNNING] `rustc --crate-name bench3 [..] benches/bench3.rs [..]` +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn check_unit_test_profile() { + let foo = project() + .file( + "src/lib.rs", + r#" + #[cfg(test)] + mod tests { + #[test] + fn it_works() { + badtext + } + } + "#, + ) + .build(); + + foo.cargo("check").run(); + foo.cargo("check --profile test") + .with_status(101) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +error[E0425]: cannot find value `badtext` in this scope +... +"#]]) + .run(); +} + +// Verify what is checked with various command-line filters. +#[cargo_test] +fn check_filters() { + let p = project() + .file( + "src/lib.rs", + r#" + fn unused_normal_lib() {} + #[cfg(test)] + mod tests { + fn unused_unit_lib() {} + } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() {} + fn unused_normal_bin() {} + #[cfg(test)] + mod tests { + fn unused_unit_bin() {} + } + "#, + ) + .file( + "tests/t1.rs", + r#" + fn unused_normal_t1() {} + #[cfg(test)] + mod tests { + fn unused_unit_t1() {} + } + "#, + ) + .file( + "examples/ex1.rs", + r#" + fn main() {} + fn unused_normal_ex1() {} + #[cfg(test)] + mod tests { + fn unused_unit_ex1() {} + } + "#, + ) + .file( + "benches/b1.rs", + r#" + fn unused_normal_b1() {} + #[cfg(test)] + mod tests { + fn unused_unit_b1() {} + } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_contains("[..]unused_normal_lib[..]") + .with_stderr_contains("[..]unused_normal_bin[..]") + .with_stderr_does_not_contain("[..]unused_normal_t1[..]") + .with_stderr_does_not_contain("[..]unused_normal_ex1[..]") + .with_stderr_does_not_contain("[..]unused_normal_b1[..]") + .with_stderr_does_not_contain("[..]unused_unit_[..]") + .run(); + p.root().join("target").rm_rf(); + p.cargo("check --tests -v") + .with_stderr_contains("[..] --crate-name foo [..] src/lib.rs [..] --test [..]") + .with_stderr_contains("[..] --crate-name foo [..] src/lib.rs [..] --crate-type lib [..]") + .with_stderr_contains("[..] --crate-name foo [..] src/main.rs [..] --test [..]") + .with_stderr_contains("[..]unused_unit_lib[..]") + .with_stderr_contains("[..]unused_unit_bin[..]") + .with_stderr_contains("[..]unused_normal_lib[..]") + .with_stderr_contains("[..]unused_normal_bin[..]") + .with_stderr_contains("[..]unused_unit_t1[..]") + .with_stderr_does_not_contain("[..]unused_normal_ex1[..]") + .with_stderr_does_not_contain("[..]unused_unit_ex1[..]") + .with_stderr_does_not_contain("[..]unused_normal_b1[..]") + .with_stderr_does_not_contain("[..]unused_unit_b1[..]") + .with_stderr_does_not_contain("[..]--crate-type bin[..]") + .run(); + p.root().join("target").rm_rf(); + p.cargo("check --test t1 -v") + .with_stderr_contains("[..]unused_normal_lib[..]") + .with_stderr_contains("[..]unused_unit_t1[..]") + .with_stderr_does_not_contain("[..]unused_unit_lib[..]") + .with_stderr_does_not_contain("[..]unused_normal_bin[..]") + .with_stderr_does_not_contain("[..]unused_unit_bin[..]") + .with_stderr_does_not_contain("[..]unused_normal_ex1[..]") + .with_stderr_does_not_contain("[..]unused_normal_b1[..]") + .with_stderr_does_not_contain("[..]unused_unit_ex1[..]") + .with_stderr_does_not_contain("[..]unused_unit_b1[..]") + .run(); + p.root().join("target").rm_rf(); + p.cargo("check --all-targets -v") + .with_stderr_contains("[..]unused_normal_lib[..]") + .with_stderr_contains("[..]unused_normal_bin[..]") + .with_stderr_contains("[..]unused_normal_t1[..]") + .with_stderr_contains("[..]unused_normal_ex1[..]") + .with_stderr_contains("[..]unused_normal_b1[..]") + .with_stderr_contains("[..]unused_unit_b1[..]") + .with_stderr_contains("[..]unused_unit_t1[..]") + .with_stderr_contains("[..]unused_unit_lib[..]") + .with_stderr_contains("[..]unused_unit_bin[..]") + .with_stderr_does_not_contain("[..]unused_unit_ex1[..]") + .run(); +} + +#[cargo_test] +fn check_artifacts() { + // Verify which artifacts are created when running check (#4059). + let p = project() + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .file("tests/t1.rs", "") + .file("examples/ex1.rs", "fn main() {}") + .file("benches/b1.rs", "") + .build(); + + p.cargo("check").run(); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); + assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 2); + + p.root().join("target").rm_rf(); + p.cargo("check --lib").run(); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); + assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); + + p.root().join("target").rm_rf(); + p.cargo("check --bin foo").run(); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); + assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 2); + + p.root().join("target").rm_rf(); + p.cargo("check --test t1").run(); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); + assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_eq!(p.glob("target/debug/t1-*").count(), 0); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); + assert_eq!(p.glob("target/debug/deps/libt1-*.rmeta").count(), 1); + + p.root().join("target").rm_rf(); + p.cargo("check --example ex1").run(); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); + assert!(!p + .root() + .join("target/debug/examples") + .join(exe("ex1")) + .is_file()); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); + assert_eq!(p.glob("target/debug/examples/libex1-*.rmeta").count(), 1); + + p.root().join("target").rm_rf(); + p.cargo("check --bench b1").run(); + assert!(!p.root().join("target/debug/libfoo.rmeta").is_file()); + assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); + assert!(!p.root().join("target/debug").join(exe("foo")).is_file()); + assert_eq!(p.glob("target/debug/b1-*").count(), 0); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rmeta").count(), 1); + assert_eq!(p.glob("target/debug/deps/libb1-*.rmeta").count(), 1); +} + +#[cargo_test] +fn short_message_format() { + let foo = project() + .file("src/lib.rs", "fn foo() { let _x: bool = 'a'; }") + .build(); + foo.cargo("check --message-format=short") + .with_status(101) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +src/lib.rs:1:27: error[E0308]: mismatched types[..] +[ERROR] could not compile `foo` (lib) due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "demo" + version = "0.0.1" + edition = "2015" + + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate proc_macro; + + use proc_macro::TokenStream; + + #[proc_macro_derive(Foo)] + pub fn demo(_input: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .file( + "src/main.rs", + r#" + #[macro_use] + extern crate demo; + + #[derive(Foo)] + struct A; + + fn main() {} + "#, + ) + .build(); + p.cargo("check -v").env("CARGO_LOG", "cargo=trace").run(); +} + +#[cargo_test] +fn check_keep_going() { + let foo = project() + .file("src/bin/one.rs", "compile_error!(\"ONE\"); fn main() {}") + .file("src/bin/two.rs", "compile_error!(\"TWO\"); fn main() {}") + .build(); + + // Due to -j1, without --keep-going only one of the two bins would be built. + foo.cargo("check -j1 --keep-going") + .with_status(101) + .with_stderr_data( + str![[r#" +[ERROR] ONE +[ERROR] TWO +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn does_not_use_empty_rustc_wrapper() { + // An empty RUSTC_WRAPPER environment variable won't be used. + // The env var will also override the config, essentially unsetting it. + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + rustc-wrapper = "do-not-execute-me" + "#, + ) + .build(); + p.cargo("check").env("RUSTC_WRAPPER", "").run(); +} + +#[cargo_test] +fn does_not_use_empty_rustc_workspace_wrapper() { + let p = project().file("src/lib.rs", "").build(); + p.cargo("check").env("RUSTC_WORKSPACE_WRAPPER", "").run(); +} + +#[cargo_test] +fn error_from_deep_recursion() -> Result<(), fmt::Error> { + let mut big_macro = String::new(); + writeln!(big_macro, "macro_rules! m {{")?; + for i in 0..130 { + writeln!(big_macro, "({}) => {{ m!({}); }};", i, i + 1)?; + } + writeln!(big_macro, "}}")?; + writeln!(big_macro, "m!(0);")?; + + let p = project().file("src/lib.rs", &big_macro).build(); + p.cargo("check --message-format=json") + .with_status(101) + .with_stdout_data(str![[r#" +{"reason":"compiler-message",[..]"message":"recursion limit reached while expanding `m!`",[..]rendered":"[..]recursion limit reached while expanding `m!`[..]"}} +... +"#]]) + .run(); + + Ok(()) +} + +#[cargo_test] +fn rustc_workspace_wrapper_affects_all_workspace_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .with_stderr_data( + str![[r#" +WRAPPER CALLED: rustc --crate-name bar [..] +WRAPPER CALLED: rustc --crate-name baz [..] +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn rustc_workspace_wrapper_includes_path_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + + [dependencies] + baz = { path = "baz" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check --workspace") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .with_stderr_data( + str![[r#" +WRAPPER CALLED: rustc --crate-name bar [..] +WRAPPER CALLED: rustc --crate-name baz [..] +WRAPPER CALLED: rustc --crate-name foo [..] +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn rustc_workspace_wrapper_respects_primary_units() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check -p bar") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .with_stderr_contains("WRAPPER CALLED: rustc --crate-name bar [..]") + .with_stdout_does_not_contain("WRAPPER CALLED: rustc --crate-name baz [..]") + .run(); +} + +#[cargo_test] +fn rustc_workspace_wrapper_excludes_published_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + + [dependencies] + baz = "1.0.0" + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + Package::new("baz", "1.0.0").publish(); + + p.cargo("check --workspace -v") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .with_stderr_contains("WRAPPER CALLED: rustc --crate-name foo [..]") + .with_stderr_contains("WRAPPER CALLED: rustc --crate-name bar [..]") + .with_stderr_contains("[CHECKING] baz [..]") + .with_stdout_does_not_contain("WRAPPER CALLED: rustc --crate-name baz [..]") + .run(); +} + +#[cargo_test] +fn warn_manifest_with_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `[project]` is deprecated in favor of `[package]` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn error_manifest_with_project_on_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + edition = "2024" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `[project]` is not supported as of the 2024 Edition, please use `[package]` + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_manifest_package_and_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [project] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] `[project]` is deprecated in favor of `[package]` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn git_manifest_package_and_project() { + let p = project(); + let git_project = git::new("bar", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + + [project] + name = "bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + }); + + let p = p + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + git = '{}' + + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.0.1 ([ROOTURL]/bar#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn git_manifest_with_project() { + let p = project(); + let git_project = git::new("bar", |p| { + p.file( + "Cargo.toml", + r#" + [project] + name = "bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + }); + + let p = p + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies.bar] + version = "0.0.1" + git = '{}' + + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.0.1 ([ROOTURL]/bar#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_fixable_warning() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "use std::io;") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +... +[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion) +... +"#]]) + .run(); +} + +#[cargo_test] +fn check_fixable_test_warning() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file( + "src/lib.rs", + "\ +mod tests { + #[test] + fn t1() { + use std::io; + } +} + ", + ) + .build(); + + foo.cargo("check --all-targets") + .with_stderr_data(str![[r#" +... +[WARNING] `foo` (lib test) generated 1 warning (run `cargo fix --lib -p foo --tests` to apply 1 suggestion) +... +"#]]) + .run(); + foo.cargo("fix --lib -p foo --tests --allow-no-vcs").run(); + assert!(!foo.read_file("src/lib.rs").contains("use std::io;")); +} + +#[cargo_test] +fn check_fixable_error_no_fix() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file( + "src/lib.rs", + "use std::io;\n#[derive(Debug(x))]\nstruct Foo;", + ) + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data( + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[ERROR] traits in `#[derive(...)]` don't accept arguments +[WARNING] unused import: `std::io` +[WARNING] `foo` (lib) generated 1 warning +[ERROR] could not compile `foo` (lib) due to 1 previous error; 1 warning emitted +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn check_fixable_warning_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("foo/src/lib.rs", "use std::io;") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + + [dependencies] + foo = { path = "../foo" } + "#, + ) + .file("bar/src/lib.rs", "use std::io;") + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion) +[WARNING] `bar` (lib) generated 1 warning (run `cargo fix --lib -p bar` to apply 1 suggestion) +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn check_fixable_example() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + "#, + ) + .file("examples/ex1.rs", "use std::fmt; fn main() {}") + .build(); + p.cargo("check --all-targets") + .with_stderr_data(str![[r#" +... +[WARNING] `foo` (example "ex1") generated 1 warning (run `cargo fix --example "ex1"` to apply 1 suggestion) +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn check_fixable_bench() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[bench] + fn bench_hello(_b: &mut test::Bencher) { + use std::io; + assert_eq!(hello(), "hello") + } + "#, + ) + .file( + "benches/bench.rs", + " + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_b: &mut test::Bencher) { use std::fmt; } + ", + ) + .build(); + p.cargo("check --all-targets") + .with_stderr_data(str![[r#" +... +[WARNING] `foo` (bench "bench") generated 1 warning (run `cargo fix --bench "bench"` to apply 1 suggestion) +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn check_fixable_mixed() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + #![feature(test)] + #[cfg(test)] + extern crate test; + + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[bench] + fn bench_hello(_b: &mut test::Bencher) { + use std::io; + assert_eq!(hello(), "hello") + } + #[test] + fn t1() { + use std::fmt; + } + "#, + ) + .file("examples/ex1.rs", "use std::fmt; fn main() {}") + .file( + "benches/bench.rs", + " + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_b: &mut test::Bencher) { use std::fmt; } + ", + ) + .build(); + p.cargo("check --all-targets") + .with_stderr_data(str![[r#" +[WARNING] `foo` (example "ex1") generated 1 warning (run `cargo fix --example "ex1"` to apply 1 suggestion) +[WARNING] `foo` (bench "bench") generated 1 warning (run `cargo fix --bench "bench"` to apply 1 suggestion) +[WARNING] `foo` (bin "foo" test) generated 2 warnings (run `cargo fix --bin "foo" --tests` to apply 2 suggestions) +... +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn check_fixable_warning_for_clippy() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + // We don't want to show a warning that is `clippy` + // specific since we are using a `rustc` wrapper + // inplace of `clippy` + .file("src/lib.rs", "use std::io;") + .build(); + + foo.cargo("check") + // We can't use `clippy` so we use a `rustc` workspace wrapper instead + .env("RUSTC_WORKSPACE_WRAPPER", tools::wrapped_clippy_driver()) + .with_stderr_data(str![[r#" +... +[WARNING] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion) +... +"#]]) + .run(); +} + +#[cargo_test] +fn check_unused_manifest_keys() { + Package::new("dep", "0.1.0").publish(); + Package::new("foo", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + + [dependencies] + dep = { version = "0.1.0", wxz = "wxz" } + foo = { version = "0.1.0", abc = "abc" } + + [dev-dependencies] + foo = { version = "0.1.0", wxz = "wxz" } + + [build-dependencies] + foo = { version = "0.1.0", wxz = "wxz" } + + [target.'cfg(windows)'.dependencies] + foo = { version = "0.1.0", wxz = "wxz" } + + [target.wasm32-wasip1.dev-dependencies] + foo = { version = "0.1.0", wxz = "wxz" } + + [target.bar.build-dependencies] + foo = { version = "0.1.0", wxz = "wxz" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[WARNING] unused manifest key: dependencies.dep.wxz +[WARNING] unused manifest key: dependencies.foo.abc +[WARNING] unused manifest key: dev-dependencies.foo.wxz +[WARNING] unused manifest key: build-dependencies.foo.wxz +[WARNING] unused manifest key: target.bar.build-dependencies.foo.wxz +[WARNING] unused manifest key: target.cfg(windows).dependencies.foo.wxz +[WARNING] unused manifest key: target.wasm32-wasip1.dev-dependencies.foo.wxz +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`) +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[CHECKING] foo v0.1.0 +[CHECKING] dep v0.1.0 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn versionless_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn pkgid_querystring_works() { + let git_project = git::new("gitdep", |p| { + p.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + edition = "2015" + + [dependencies] + gitdep = {{ git = "{}", branch = "master" }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + let output = p.cargo("pkgid").arg("gitdep").run(); + let gitdep_pkgid = String::from_utf8(output.stdout).unwrap(); + let gitdep_pkgid = gitdep_pkgid.trim(); + assert_e2e().eq( + gitdep_pkgid, + str!["git+[ROOTURL]/gitdep?branch=master#1.0.0"], + ); + + p.cargo("build -p") + .arg(gitdep_pkgid) + .with_stderr_data(str![[r#" +[COMPILING] gitdep v1.0.0 ([ROOTURL]/gitdep?branch=master#[..]) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check_cfg.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check_cfg.rs new file mode 100644 index 000000000..2e0325433 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/check_cfg.rs @@ -0,0 +1,931 @@ +//! Tests for Cargo usage of rustc `--check-cfg`. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, project, str}; + +macro_rules! x { + ($tool:tt => $what:tt $(of $who:tt)?) => {{ + #[cfg(windows)] + { + concat!("[RUNNING] [..]", $tool, "[..] --check-cfg ", + $what, '(', $($who,)* ')', "[..]") + } + #[cfg(not(windows))] + { + concat!("[RUNNING] [..]", $tool, "[..] --check-cfg '", + $what, '(', $($who,)* ')', "'", "[..]") + } + }}; + ($tool:tt => $what:tt of $who:tt with $($first_value:tt $($other_values:tt)*)?) => {{ + #[cfg(windows)] + { + concat!("[RUNNING] [..]", $tool, "[..] --check-cfg \"", + $what, '(', $who, ", values(", $("/\"", $first_value, "/\"", $(", ", "/\"", $other_values, "/\"",)*)* "))", '"', "[..]") + } + #[cfg(not(windows))] + { + concat!("[RUNNING] [..]", $tool, "[..] --check-cfg '", + $what, '(', $who, ", values(", $("\"", $first_value, "\"", $(", ", "\"", $other_values, "\"",)*)* "))", "'", "[..]") + } + }}; +} + +#[cargo_test] +fn features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + f_a = [] + f_b = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "f_a" "f_b")) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn features_with_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar/" } + + [features] + f_a = [] + f_b = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[allow(dead_code)] fn bar() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "f_a" "f_b")) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn features_with_opt_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar/", optional = true } + + [features] + default = ["bar"] + f_a = [] + f_b = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[allow(dead_code)] fn bar() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "bar" "default" "f_a" "f_b")) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn features_with_namespaced_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar/", optional = true } + + [features] + f_a = ["dep:bar"] + f_b = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[allow(dead_code)] fn bar() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "f_a" "f_b")) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn features_fingerprint() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + f_a = [] + f_b = [] + "#, + ) + .file("src/lib.rs", "#[cfg(feature = \"f_b\")] fn entry() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "f_a" "f_b")) + .with_stderr_does_not_contain("[..]unexpected_cfgs[..]") + .run(); + + p.cargo("check -v") + .with_stderr_does_not_contain("[..]rustc[..]") + .run(); + + // checking that re-ordering the features does not invalid the fingerprint + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + f_b = [] + f_a = [] + "#, + ); + + p.cargo("check -v") + .with_stderr_does_not_contain("[..]rustc[..]") + .run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + f_a = [] + "#, + ); + + p.cargo("check -v") + // we check that the fingerprint is indeed dirty + // that is cause rustc to be called again with the new check-cfg args + // and that we indeed found a new warning from the unexpected_cfgs lint + .with_stderr_data(format!( + "\ +[DIRTY] foo v0.1.0 ([ROOT]/foo): the list of declared features changed +[CHECKING] foo v0.1.0 ([ROOT]/foo) +{running_rustc} +[WARNING] unexpected `cfg` condition value: `f_b` +... +", + running_rustc = x!("rustc" => "cfg" of "feature" with "f_a") + )) + .run(); +} + +#[cargo_test] +fn well_known_names_values() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with)) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn features_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + f_a = [] + f_b = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("test -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "f_a" "f_b")) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn features_doctest() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + default = ["f_a"] + f_a = [] + f_b = [] + "#, + ) + .file("src/lib.rs", "#[allow(dead_code)] fn foo() {}") + .build(); + + p.cargo("test -v --doc") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "default" "f_a" "f_b")) + .with_stderr_contains(x!("rustdoc" => "cfg" of "feature" with "default" "f_a" "f_b")) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .with_stderr_contains(x!("rustdoc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn well_known_names_values_test() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("test -v") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with)) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn well_known_names_values_doctest() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "#[allow(dead_code)] fn foo() {}") + .build(); + + p.cargo("test -v --doc") + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with)) + .with_stderr_contains(x!("rustdoc" => "cfg" of "feature" with)) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .with_stderr_contains(x!("rustdoc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn features_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + default = ["f_a"] + f_a = [] + f_b = [] + "#, + ) + .file("src/lib.rs", "#[allow(dead_code)] fn foo() {}") + .build(); + + p.cargo("doc -v") + .with_stderr_contains(x!("rustdoc" => "cfg" of "feature" with "default" "f_a" "f_b")) + .with_stderr_contains(x!("rustdoc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn build_script_feedback() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-check-cfg=cfg(foo)"); }"#, + ) + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "foo")) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn build_script_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-check-cfg=cfg(foo)"); }"#, + ) + .build(); + + p.cargo("doc -v") + .with_stderr_does_not_contain("rustc [..] --check-cfg [..]") + .with_stderr_data(format!( + "\ +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] build.rs [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +{running_rustdoc} +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html +", + running_rustdoc = x!("rustdoc" => "cfg" of "foo") + )) + .run(); +} + +#[cargo_test] +fn build_script_override() { + let target = cargo_test_support::rustc_host(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + links = "a" + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("build.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.a] + rustc-check-cfg = ["cfg(foo)"] + "#, + target + ), + ) + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "foo")) + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with)) + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) + .run(); +} + +#[cargo_test] +fn build_script_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + r#"fn main() { + println!("cargo::rustc-check-cfg=cfg(foo)"); + println!("cargo::rustc-cfg=foo"); + }"#, + ) + .file( + "src/lib.rs", + r#" + /// + /// ``` + /// extern crate foo; + /// + /// fn main() { + /// foo::foo() + /// } + /// ``` + /// + #[cfg(foo)] + pub fn foo() {} + + #[cfg(foo)] + #[test] + fn test_foo() { + foo() + } + "#, + ) + .file("tests/test.rs", "#[cfg(foo)] #[test] fn test_bar() {}") + .build(); + + p.cargo("test -v") + .with_stderr_data( + format!( + "\ +{running_rustc} +{running_rustdoc} +... +", + running_rustc = x!("rustc" => "cfg" of "foo"), + running_rustdoc = x!("rustdoc" => "cfg" of "foo") + ) + .unordered(), + ) + .with_stdout_data( + str![[r#" +test test_foo ... ok +test test_bar ... ok +test [..] ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn config_simple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(has_foo)", "cfg(has_bar, values(\"yes\", \"no\"))"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "has_foo")) + .with_stderr_contains(x!("rustc" => "cfg" of "has_bar" with "yes" "no")) + .with_stderr_does_not_contain("[..]unused manifest key[..]") + .run(); +} + +#[cargo_test] +fn config_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo/"] + + [workspace.lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(has_foo)"] } + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints] + workspace = true + "#, + ) + .file("foo/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v") + .with_stderr_data(format!( + "\ +... +{running_rustc} +... +", + running_rustc = x!("rustc" => "cfg" of "has_foo") + )) + .with_stderr_does_not_contain("unexpected_cfgs") + .run(); +} + +#[cargo_test] +fn config_workspace_not_inherited() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo/"] + + [workspace.lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(has_foo)"] } + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("foo/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v") + .with_stderr_does_not_contain(x!("rustc" => "cfg" of "has_foo")) + .with_stderr_does_not_contain("unexpected_cfgs") + .run(); +} + +#[cargo_test] +fn config_invalid_position() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + use_bracket = { level = "warn", check-cfg = ["cfg(has_foo)"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[WARNING] unused manifest key: `lints.rust.use_bracket.check-cfg` +... +"#]]) + .with_stderr_does_not_contain(x!("rustc" => "cfg" of "has_foo")) + .run(); +} + +#[cargo_test] +fn config_invalid_empty() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] missing field `level` +... +"#]]) + .run(); +} + +#[cargo_test] +fn config_invalid_not_list() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = "cfg()" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `lints.rust.unexpected_cfgs.check-cfg` must be a list of string + +"#]]) + .run(); +} + +#[cargo_test] +fn config_invalid_not_list_string() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = [12] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `lints.rust.unexpected_cfgs.check-cfg` must be a list of string + +"#]]) + .run(); +} + +#[cargo_test] +fn config_and_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + my_feature = [] + alloc = [] + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(has_foo)", "cfg(has_bar, values(\"yes\", \"no\"))"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "has_foo")) + .with_stderr_contains(x!("rustc" => "cfg" of "has_bar" with "yes" "no")) + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "alloc" "my_feature")) + .run(); +} + +#[cargo_test] +fn config_with_cargo_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(has_foo)"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("doc -v") + .with_stderr_data(format!( + "\ +... +{running_rustdoc} +... +", + running_rustdoc = x!("rustdoc" => "cfg" of "has_foo") + )) + .run(); +} + +#[cargo_test] +fn config_with_cargo_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(has_foo)"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("test -v") + .with_stderr_data(format!( + "\ +... +{running_rustc} +... +", + running_rustc = x!("rustc" => "cfg" of "has_foo") + )) + .run(); +} + +#[cargo_test] +fn config_and_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + build = "build.rs" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bar)"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-check-cfg=cfg(foo)"); }"#, + ) + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "foo")) // from build.rs + .with_stderr_contains(x!("rustc" => "cfg" of "bar")) // from config + .run(); +} + +#[cargo_test] +fn config_features_and_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + build = "build.rs" + + [features] + serde = [] + json = [] + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bar)"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#"fn main() { println!("cargo::rustc-check-cfg=cfg(foo)"); }"#, + ) + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "foo")) // from build.rs + .with_stderr_contains(x!("rustc" => "cfg" of "bar")) // from config + .with_stderr_contains(x!("rustc" => "cfg" of "feature" with "json" "serde")) // features + .with_stderr_contains(x!("rustc" => "cfg" of "docsrs,test")) // Cargo well known + .run(); +} + +#[cargo_test] +fn config_fingerprint() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bar)"] } + "#, + ) + .file("src/lib.rs", "fn entry() {}") + .build(); + + p.cargo("check -v") + .with_stderr_contains(x!("rustc" => "cfg" of "bar")) + .run(); + + p.cargo("check -v") + .with_stderr_does_not_contain("[..]rustc[..]") + .run(); + + // checking that changing the `check-cfg` config does invalid the fingerprint + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lints.rust] + unexpected_cfgs = { level = "warn", check-cfg = ["cfg(bar)", "cfg(foo)"] } + "#, + ); + + p.cargo("check -v") + // we check that the fingerprint is indeed dirty + .with_stderr_contains("[..][DIRTY][..]the profile configuration changed") + // that cause rustc to be called again with the new check-cfg args + .with_stderr_contains(x!("rustc" => "cfg" of "bar")) + .with_stderr_contains(x!("rustc" => "cfg" of "foo")) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/clean.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/clean.rs new file mode 100644 index 000000000..5a510f664 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/clean.rs @@ -0,0 +1,921 @@ +//! Tests for the `cargo clean` command. + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{ + basic_bin_manifest, basic_manifest, git, main_file, project, project_in, rustc_host, +}; +use glob::GlobError; +use std::env; +use std::path::{Path, PathBuf}; + +#[cargo_test] +fn cargo_clean_simple() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build").run(); + assert!(p.build_dir().is_dir()); + + p.cargo("clean").run(); + assert!(!p.build_dir().is_dir()); +} + +#[cargo_test] +fn different_dir() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .file("src/bar/a.rs", "") + .build(); + + p.cargo("build").run(); + assert!(p.build_dir().is_dir()); + + p.cargo("clean") + .cwd("src") + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + assert!(!p.build_dir().is_dir()); +} + +#[cargo_test] +fn clean_multiple_packages() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "d1" + [dependencies.d2] + path = "d2" + + [[bin]] + name = "foo" + "#, + ) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .file("d1/Cargo.toml", &basic_bin_manifest("d1")) + .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }") + .file("d2/Cargo.toml", &basic_bin_manifest("d2")) + .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }") + .build(); + + p.cargo("build -p d1 -p d2 -p foo").run(); + + let d1_path = &p + .build_dir() + .join("debug") + .join(format!("d1{}", env::consts::EXE_SUFFIX)); + let d2_path = &p + .build_dir() + .join("debug") + .join(format!("d2{}", env::consts::EXE_SUFFIX)); + + assert!(p.bin("foo").is_file()); + assert!(d1_path.is_file()); + assert!(d2_path.is_file()); + + p.cargo("clean -p d1 -p d2") + .cwd("src") + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + assert!(p.bin("foo").is_file()); + assert!(!d1_path.is_file()); + assert!(!d2_path.is_file()); +} + +#[cargo_test] +fn clean_multiple_packages_in_glob_char_path() { + let p = project_in("[d1]") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + let foo_path = &p.build_dir().join("debug").join("deps"); + + #[cfg(not(target_env = "msvc"))] + let file_glob = "foo-*"; + + #[cfg(target_env = "msvc")] + let file_glob = "foo.pdb"; + + // Assert that build artifacts are produced + p.cargo("build").run(); + assert_ne!(get_build_artifacts(foo_path, file_glob).len(), 0); + + // Assert that build artifacts are destroyed + p.cargo("clean -p foo").run(); + assert_eq!(get_build_artifacts(foo_path, file_glob).len(), 0); +} + +fn get_build_artifacts(path: &PathBuf, file_glob: &str) -> Vec> { + let pattern = path.to_str().expect("expected utf-8 path"); + let pattern = glob::Pattern::escape(pattern); + + let path = PathBuf::from(pattern).join(file_glob); + let path = path.to_str().expect("expected utf-8 path"); + glob::glob(path) + .expect("expected glob to run") + .into_iter() + .collect::>>() +} + +#[cargo_test] +fn clean_p_only_cleans_specified_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [ + "foo", + "foo_core", + "foo-base", + ] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "//! foo") + .file("foo_core/Cargo.toml", &basic_manifest("foo_core", "0.1.0")) + .file("foo_core/src/lib.rs", "//! foo_core") + .file("foo-base/Cargo.toml", &basic_manifest("foo-base", "0.1.0")) + .file("foo-base/src/lib.rs", "//! foo-base") + .build(); + + let fingerprint_path = &p.build_dir().join("debug").join(".fingerprint"); + + p.cargo("build -p foo -p foo_core -p foo-base").run(); + + let mut fingerprint_names = get_fingerprints_without_hashes(fingerprint_path); + + // Artifacts present for all after building + assert!(fingerprint_names.iter().any(|e| e == "foo")); + let num_foo_core_artifacts = fingerprint_names + .iter() + .filter(|&e| e == "foo_core") + .count(); + assert_ne!(num_foo_core_artifacts, 0); + let num_foo_base_artifacts = fingerprint_names + .iter() + .filter(|&e| e == "foo-base") + .count(); + assert_ne!(num_foo_base_artifacts, 0); + + p.cargo("clean -p foo").run(); + + fingerprint_names = get_fingerprints_without_hashes(fingerprint_path); + + // Cleaning `foo` leaves artifacts for the others + assert!(!fingerprint_names.iter().any(|e| e == "foo")); + assert_eq!( + fingerprint_names + .iter() + .filter(|&e| e == "foo_core") + .count(), + num_foo_core_artifacts, + ); + assert_eq!( + fingerprint_names + .iter() + .filter(|&e| e == "foo-base") + .count(), + num_foo_core_artifacts, + ); +} + +fn get_fingerprints_without_hashes(fingerprint_path: &Path) -> Vec { + std::fs::read_dir(fingerprint_path) + .expect("Build dir should be readable") + .filter_map(|entry| entry.ok()) + .map(|entry| { + let name = entry.file_name(); + let name = name + .into_string() + .expect("fingerprint name should be UTF-8"); + name.rsplit_once('-') + .expect("Name should contain at least one hyphen") + .0 + .to_owned() + }) + .collect() +} + +#[cargo_test] +fn clean_release() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build --release").run(); + + p.cargo("clean -p foo").run(); + p.cargo("build --release") + .with_stderr_data(str![[r#" +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("clean -p foo --release").run(); + p.cargo("build --release") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build").run(); + + p.cargo("clean").arg("--release").run(); + assert!(p.build_dir().is_dir()); + assert!(p.build_dir().join("debug").is_dir()); + assert!(!p.build_dir().join("release").is_dir()); +} + +#[cargo_test] +fn clean_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("doc").run(); + + let doc_path = &p.build_dir().join("doc"); + + assert!(doc_path.is_dir()); + + p.cargo("clean --doc") + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + + assert!(!doc_path.is_dir()); + assert!(p.build_dir().is_dir()); +} + +#[cargo_test] +fn build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + use std::path::PathBuf; + use std::env; + + fn main() { + let out = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + if env::var("FIRST").is_ok() { + std::fs::File::create(out.join("out")).unwrap(); + } else { + assert!(!out.join("out").exists()); + } + } + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build").env("FIRST", "1").run(); + p.cargo("clean -p foo").run(); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] build.rs [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/main.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn clean_git() { + let git = git::new("dep", |project| { + project + .file("Cargo.toml", &basic_manifest("dep", "0.5.0")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + dep = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); + p.cargo("clean -p dep") + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + p.cargo("build").run(); +} + +#[cargo_test] +fn registry() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.1.0").publish(); + + p.cargo("build").run(); + p.cargo("clean -p bar") + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + p.cargo("build").run(); +} + +#[cargo_test] +fn clean_verbose() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.1.0").publish(); + + p.cargo("build").run(); + let mut expected = String::from( + "\ +[REMOVING] [ROOT]/foo/target/debug/.fingerprint/bar-[HASH] +[REMOVING] [ROOT]/foo/target/debug/deps/libbar-[HASH].rlib +[REMOVING] [ROOT]/foo/target/debug/deps/bar-[HASH].d +[REMOVING] [ROOT]/foo/target/debug/deps/libbar-[HASH].rmeta +", + ); + if cfg!(target_os = "macos") { + // Rust 1.69 has changed so that split-debuginfo=unpacked includes unpacked for rlibs. + for _ in p.glob("target/debug/deps/bar-*.o") { + expected.push_str("[REMOVING] [ROOT]/foo/target/debug/deps/bar-[HASH][..].o\n"); + } + } + expected.push_str("[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total\n"); + p.cargo("clean -p bar --verbose") + .with_stderr_data(&expected.unordered()) + .run(); + p.cargo("build").run(); +} + +#[cargo_test] +fn clean_remove_rlib_rmeta() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build").run(); + assert!(p.target_debug_dir().join("libfoo.rlib").exists()); + let rmeta = p.glob("target/debug/deps/*.rmeta").next().unwrap().unwrap(); + assert!(rmeta.exists()); + p.cargo("clean -p foo").run(); + assert!(!p.target_debug_dir().join("libfoo.rlib").exists()); + assert!(!rmeta.exists()); +} + +#[cargo_test] +fn package_cleans_all_the_things() { + // -p cleans everything + // Use dashes everywhere to make sure dash/underscore stuff is handled. + for crate_type in &["rlib", "dylib", "cdylib", "staticlib", "proc-macro"] { + // Try each crate type individually since the behavior changes when + // they are combined. + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo-bar" + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["{}"] + "#, + crate_type + ), + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build").run(); + p.cargo("clean -p foo-bar").run(); + assert_all_clean(&p.build_dir()); + } + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo-bar" + version = "0.1.0" + edition = "2018" + + [lib] + crate-type = ["rlib", "dylib", "staticlib"] + + [[example]] + name = "foo-ex-rlib" + crate-type = ["rlib"] + test = true + + [[example]] + name = "foo-ex-cdylib" + crate-type = ["cdylib"] + test = true + + [[example]] + name = "foo-ex-bin" + test = true + "#, + ) + .file("src/lib.rs", "") + .file("src/lib/some-main.rs", "fn main() {}") + .file("src/bin/other-main.rs", "fn main() {}") + .file("examples/foo-ex-rlib.rs", "") + .file("examples/foo-ex-cdylib.rs", "") + .file("examples/foo-ex-bin.rs", "fn main() {}") + .file("tests/foo-test.rs", "") + .file("benches/foo-bench.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("build --all-targets") + .env("CARGO_INCREMENTAL", "1") + .run(); + p.cargo("test --all-targets") + .env("CARGO_INCREMENTAL", "1") + .run(); + p.cargo("check --all-targets") + .env("CARGO_INCREMENTAL", "1") + .run(); + p.cargo("clean -p foo-bar").run(); + assert_all_clean(&p.build_dir()); + + // Try some targets. + p.cargo("build --all-targets --target") + .arg(rustc_host()) + .run(); + p.cargo("clean -p foo-bar --target").arg(rustc_host()).run(); + assert_all_clean(&p.build_dir()); +} + +// Ensures that all files for the package have been deleted. +#[track_caller] +fn assert_all_clean(build_dir: &Path) { + let walker = walkdir::WalkDir::new(build_dir).into_iter(); + for entry in walker.filter_entry(|e| { + let path = e.path(); + // This is a known limitation, clean can't differentiate between + // the different build scripts from different packages. + !(path + .file_name() + .unwrap() + .to_str() + .unwrap() + .starts_with("build_script_build") + && path + .parent() + .unwrap() + .file_name() + .unwrap() + .to_str() + .unwrap() + == "incremental") + }) { + let entry = entry.unwrap(); + let path = entry.path(); + if let ".rustc_info.json" | ".cargo-lock" | "CACHEDIR.TAG" = + path.file_name().unwrap().to_str().unwrap() + { + continue; + } + if path.is_symlink() || path.is_file() { + panic!("{:?} was not cleaned", path); + } + } +} + +#[cargo_test] +fn clean_spec_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" + edition = "2015" + + [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_data(str![[r#" +[ERROR] package ID specification `baz` did not match any packages + +[HELP] a package with a similar name exists: `bar` + +"#]]) + .run(); + + p.cargo("clean -p bar:0.1.0") + .with_stderr_data(str![[r#" +[WARNING] version qualifier in `-p bar:0.1.0` is ignored, cleaning all versions of `bar` found +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B 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" + edition = "2015" + + [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_data(str![[r#" +[ERROR] package ID specification `baz` did not match any packages + +[HELP] a package with a similar name exists: `bar` + +"#]]) + .run(); + + p.cargo("clean -p bar:0.1") + .with_stderr_data(str![[r#" +[WARNING] version qualifier in `-p bar:0.1` is ignored, cleaning all versions of `bar` found +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B 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( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [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_data(str![[r#" +[ERROR] package ID specification `baz` did not match any packages + +[HELP] a package with a similar name exists: `bar` + +"#]]) + .run(); + + p.cargo("clean -p bar:0") + .with_stderr_data(str![[r#" +[WARNING] version qualifier in `-p bar:0` is ignored, cleaning all versions of `bar` found +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B 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_reserved() { + // Clean when a target (like a test) has a reserved name. In this case, + // make sure `clean -p` doesn't delete the reserved directory `build` when + // there is a test named `build`. + Package::new("bar", "1.0.0") + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file("tests/build.rs", "") + .build(); + + p.cargo("build --all-targets").run(); + assert!(p.target_debug_dir().join("build").is_dir()); + let build_test = p.glob("target/debug/deps/build-*").next().unwrap().unwrap(); + assert!(build_test.exists()); + // Tests are never "uplifted". + assert!(p.glob("target/debug/build-*").next().is_none()); + + p.cargo("clean -p foo").run(); + // Should not delete this. + assert!(p.target_debug_dir().join("build").is_dir()); + + // This should not rebuild bar. + p.cargo("build -v --all-targets") + .with_stderr_data(str![[r#" +[FRESH] bar v1.0.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .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" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Start with no files. + p.cargo("clean --dry-run") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[SUMMARY] 0 files +[WARNING] no files deleted due to --dry-run + +"#]]) + .run(); + p.cargo("check").run(); + let before = p.build_dir().ls_r(); + p.cargo("clean --dry-run") + .with_stderr_data(str![[r#" +[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total +[WARNING] no files deleted due to --dry-run + +"#]]) + .run(); + // Verify it didn't delete anything. + let after = p.build_dir().ls_r(); + assert_eq!(before, after); + let mut expected = itertools::join(before.iter().map(|p| p.to_str().unwrap()), "\n"); + expected.push_str("\n"); + let expected = snapbox::filter::normalize_paths(&expected); + let expected = assert_e2e().redactions().redact(&expected); + eprintln!("{expected}"); + // Verify the verbose output. + p.cargo("clean --dry-run -v") + .with_stdout_data(expected.unordered()) + .with_stderr_data(str![[r#" +[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total +[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_data(str![[r#" +[ERROR] --doc cannot be used with -p + +"#]]) + .run(); +} + +#[cargo_test] +fn quiet_does_not_show_summary() { + // Checks that --quiet works with `cargo clean`, since there was a + // subtle issue with how the flag is defined as a global flag. + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + p.cargo("clean --quiet --dry-run") + .with_stdout_data("") + .with_stderr_data("") + .run(); + // Verify exact same command without -q would actually display something. + p.cargo("clean --dry-run") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total +[WARNING] no files deleted due to --dry-run + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/collisions.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/collisions.rs new file mode 100644 index 000000000..1f69f3e7f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/collisions.rs @@ -0,0 +1,593 @@ +//! Tests for when multiple artifacts have the same output filename. +//! See for more details. +//! Ideally these should never happen, but I don't think we'll ever be able to +//! prevent all collisions. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, cross_compile, project}; +use std::env; + +#[cargo_test] +fn collision_dylib() { + // Path dependencies don't include metadata hash in filename for dylibs. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "1.0.0" + edition = "2015" + + [lib] + crate-type = ["dylib"] + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "1.0.0" + edition = "2015" + + [lib] + crate-type = ["dylib"] + name = "a" + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + // `j=1` is required because on Windows you'll get an error due to + // two processes writing to the file at the same time. + p.cargo("build -j=1") + .with_stderr_data(&format!("\ +... +[WARNING] output filename collision. +The lib target `a` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([ROOT]/foo/a)`. +Colliding filename is: [ROOT]/foo/target/debug/deps/{}a{} +The targets should have unique names. +Consider changing their names to be unique or compiling them separately. +This may become a hard error in the future; see . +... +", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX)) + .run(); +} + +#[cargo_test] +fn collision_example() { + // Examples in a workspace can easily collide. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "1.0.0")) + .file("a/examples/ex1.rs", "fn main() {}") + .file("b/Cargo.toml", &basic_manifest("b", "1.0.0")) + .file("b/examples/ex1.rs", "fn main() {}") + .build(); + + // `j=1` is required because on Windows you'll get an error due to + // two processes writing to the file at the same time. + p.cargo("build --examples -j=1") + .with_stderr_data(str![[r#" +... +[WARNING] output filename collision. +The example target `ex1` in package `b v1.0.0 ([ROOT]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([ROOT]/foo/a)`. +Colliding filename is: [ROOT]/foo/target/debug/examples/ex1[EXE] +The targets should have unique names. +Consider changing their names to be unique or compiling them separately. +This may become a hard error in the future; see . +... + +"#]]) + .run(); +} + +#[cargo_test] +// See https://github.com/rust-lang/cargo/issues/7493 +#[cfg_attr( + any(target_env = "msvc", target_vendor = "apple"), + ignore = "--artifact-dir and examples are currently broken on MSVC and apple" +)] +fn collision_export() { + // `--artifact-dir` combines some things which can cause conflicts. + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("examples/foo.rs", "fn main() {}") + .file("src/main.rs", "fn main() {}") + .build(); + + // -j1 to avoid issues with two processes writing to the same file at the + // same time. + p.cargo("build -j1 --artifact-dir=out -Z unstable-options --bins --examples") + .masquerade_as_nightly_cargo(&["artifact-dir"]) + .with_stderr_data(str![[r#" +[WARNING] `--artifact-dir` filename collision. +The example target `foo` in package `foo v1.0.0 ([ROOT]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([ROOT]/foo)`. +Colliding filename is: [ROOT]/foo/out/foo[EXE] +The exported filenames should be unique. +Consider changing their names to be unique or compiling them separately. +This may become a hard error in the future; see . +... + +"#]]) + .run(); +} + +#[cargo_test] +fn collision_doc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + foo2 = { path = "foo2" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo2/Cargo.toml", + r#" + [package] + name = "foo2" + version = "0.1.0" + edition = "2015" + + [lib] + name = "foo" + "#, + ) + .file("foo2/src/lib.rs", "") + .build(); + + p.cargo("doc -j=1") + .with_stderr_data(str![[r#" +... +[WARNING] output filename collision. +The lib target `foo` in package `foo2 v0.1.0 ([ROOT]/foo/foo2)` has the same output filename as the lib target `foo` in package `foo v0.1.0 ([ROOT]/foo)`. +Colliding filename is: [ROOT]/foo/target/doc/foo/index.html +The targets should have unique names. +This is a known bug where multiple crates with the same name use +the same path; see . +... + +"#]]) + .run(); +} + +#[cargo_test] +fn collision_doc_multiple_versions() { + // Multiple versions of the same package. + Package::new("old-dep", "1.0.0").publish(); + Package::new("bar", "1.0.0").dep("old-dep", "1.0").publish(); + // Note that this removes "old-dep". Just checking what happens when there + // are orphans. + Package::new("bar", "2.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + bar2 = { package="bar", version="2.0" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Should only document bar 2.0, should not document old-dep. + p.cargo("doc") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[ADDING] bar v1.0.0 (available: v2.0.0) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v2.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] old-dep v1.0.0 (registry `dummy-registry`) +[CHECKING] old-dep v1.0.0 +[CHECKING] bar v2.0.0 +[CHECKING] bar v1.0.0 +[DOCUMENTING] bar v2.0.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn collision_doc_host_target_feature_split() { + // Same dependency built twice due to different features. + // + // foo v0.1.0 + // ├── common v1.0.0 + // │ └── common-dep v1.0.0 + // └── pm v0.1.0 (proc-macro) + // └── common v1.0.0 + // └── common-dep v1.0.0 + // [build-dependencies] + // └── common-dep v1.0.0 + // + // Here `common` and `common-dep` are built twice. `common-dep` has + // different features for host versus target. + Package::new("common-dep", "1.0.0") + .feature("bdep-feat", &[]) + .file( + "src/lib.rs", + r#" + /// Some doc + pub fn f() {} + + /// Another doc + #[cfg(feature = "bdep-feat")] + pub fn bdep_func() {} + "#, + ) + .publish(); + Package::new("common", "1.0.0") + .dep("common-dep", "1.0") + .file( + "src/lib.rs", + r#" + /// Some doc + pub fn f() {} + "#, + ) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [dependencies] + pm = { path = "pm" } + common = "1.0" + + [build-dependencies] + common-dep = { version = "1.0", features = ["bdep-feat"] } + "#, + ) + .file( + "src/lib.rs", + r#" + /// Some doc + pub fn f() {} + "#, + ) + .file("build.rs", "fn main() {}") + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2018" + + [lib] + proc-macro = true + + [dependencies] + common = "1.0" + "#, + ) + .file( + "pm/src/lib.rs", + r#" + use proc_macro::TokenStream; + + /// Some doc + #[proc_macro] + pub fn pm(_input: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .build(); + + // No warnings, no duplicates, common and common-dep only documented once. + p.cargo("doc") + // Cannot check full output due to https://github.com/rust-lang/cargo/issues/9076 + .with_stderr_does_not_contain("[WARNING][..]") + .run(); + + assert!(p.build_dir().join("doc/common_dep/fn.f.html").exists()); + assert!(!p + .build_dir() + .join("doc/common_dep/fn.bdep_func.html") + .exists()); + assert!(p.build_dir().join("doc/common/fn.f.html").exists()); + assert!(p.build_dir().join("doc/pm/macro.pm.html").exists()); + assert!(p.build_dir().join("doc/foo/fn.f.html").exists()); +} + +#[cargo_test] +fn collision_doc_profile_split() { + // Same dependency built twice due to different profile settings. + Package::new("common", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + pm = { path = "pm" } + common = "1.0" + + [profile.dev] + opt-level = 2 + "#, + ) + .file("src/lib.rs", "") + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + + [dependencies] + common = "1.0" + + [lib] + proc-macro = true + "#, + ) + .file("pm/src/lib.rs", "") + .build(); + + // Just to verify that common is normally built twice. + // This is unordered because in rare cases `pm` may start + // building in-between the two `common`. + p.cargo("build -v") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] common v1.0.0 (registry `dummy-registry`) +[COMPILING] common v1.0.0 +[RUNNING] `rustc --crate-name common [..] +[RUNNING] `rustc --crate-name common [..] +[COMPILING] pm v0.1.0 ([ROOT]/foo/pm) +[RUNNING] `rustc --crate-name pm [..] +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + // Should only document common once, no warnings. + p.cargo("doc") + .with_stderr_data( + str![[r#" +[CHECKING] common v1.0.0 +[DOCUMENTING] common v1.0.0 +[DOCUMENTING] pm v0.1.0 ([ROOT]/foo/pm) +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn collision_doc_sources() { + // Different sources with the same package. + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + bar2 = { path = "bar", package = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("doc -j=1") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[WARNING] output filename collision. +The lib target `bar` in package `bar v1.0.0` has the same output filename as the lib target `bar` in package `bar v1.0.0 ([ROOT]/foo/bar)`. +Colliding filename is: [ROOT]/foo/target/doc/bar/index.html +The targets should have unique names. +This is a known bug where multiple crates with the same name use +the same path; see . +[CHECKING] bar v1.0.0 ([ROOT]/foo/bar) +[DOCUMENTING] bar v1.0.0 ([ROOT]/foo/bar) +[DOCUMENTING] bar v1.0.0 +[CHECKING] bar v1.0.0 +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn collision_doc_target() { + // collision in doc with --target, doesn't fail due to orphans + if cross_compile::disabled() { + return; + } + + Package::new("orphaned", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .dep("orphaned", "1.0") + .publish(); + Package::new("bar", "2.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar2 = { version = "2.0", package="bar" } + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc --target") + .arg(cross_compile::alternate()) + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[ADDING] bar v1.0.0 (available: v2.0.0) +[DOWNLOADING] crates ... +[DOWNLOADED] orphaned v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v2.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] orphaned v1.0.0 +[DOCUMENTING] bar v2.0.0 +[CHECKING] bar v2.0.0 +[CHECKING] bar v1.0.0 +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/[ALT_TARGET]/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn collision_with_root() { + // Check for a doc collision between a root package and a dependency. + // In this case, `foo-macro` comes from both the workspace and crates.io. + // This checks that the duplicate correction code doesn't choke on this + // by removing the root unit. + Package::new("foo-macro", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["abc", "foo-macro"] + "#, + ) + .file( + "abc/Cargo.toml", + r#" + [package] + name = "abc" + version = "1.0.0" + edition = "2015" + + [dependencies] + foo-macro = "1.0" + "#, + ) + .file("abc/src/lib.rs", "") + .file( + "foo-macro/Cargo.toml", + r#" + [package] + name = "foo-macro" + version = "1.0.0" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + abc = {path="../abc"} + "#, + ) + .file("foo-macro/src/lib.rs", "") + .build(); + + p.cargo("doc -j=1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] foo-macro v1.0.0 (registry `dummy-registry`) +[WARNING] output filename collision. +The lib target `foo_macro` in package `foo-macro v1.0.0` has the same output filename as the lib target `foo_macro` in package `foo-macro v1.0.0 ([ROOT]/foo/foo-macro)`. +Colliding filename is: [ROOT]/foo/target/doc/foo_macro/index.html +The targets should have unique names. +This is a known bug where multiple crates with the same name use +the same path; see . +[CHECKING] foo-macro v1.0.0 +[DOCUMENTING] foo-macro v1.0.0 +[CHECKING] abc v1.0.0 ([ROOT]/foo/abc) +[DOCUMENTING] foo-macro v1.0.0 ([ROOT]/foo/foo-macro) +[DOCUMENTING] abc v1.0.0 ([ROOT]/foo/abc) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/abc/index.html and 1 other file + +"#]].unordered()) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/concurrent.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/concurrent.rs new file mode 100644 index 000000000..3d48c39b6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/concurrent.rs @@ -0,0 +1,510 @@ +//! Tests for running multiple `cargo` processes at the same time. + +use std::fs; +use std::net::TcpListener; +use std::process::Stdio; +use std::sync::mpsc::channel; +use std::thread; +use std::{env, str}; + +use cargo_test_support::cargo_process; +use cargo_test_support::git; +use cargo_test_support::install::assert_has_installed_exe; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, execs, project, slow_cpu_multiplier}; + +fn pkg(name: &str, vers: &str) { + Package::new(name, vers) + .file("src/main.rs", "fn main() {{}}") + .publish(); +} + +#[cargo_test] +fn multiple_installs() { + let p = project() + .no_manifest() + .file("a/Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file("a/src/main.rs", "fn main() {}") + .file("b/Cargo.toml", &basic_manifest("bar", "0.0.0")) + .file("b/src/main.rs", "fn main() {}"); + let p = p.build(); + + let mut a = p.cargo("install").cwd("a").build_command(); + let mut b = p.cargo("install").cwd("b").build_command(); + + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + execs().run_output(&a); + execs().run_output(&b); + + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_installed_exe(paths::cargo_home(), "bar"); +} + +#[cargo_test] +fn concurrent_installs() { + const LOCKED_BUILD: &str = "waiting for file lock on build directory"; + + pkg("foo", "0.0.1"); + pkg("bar", "0.0.1"); + + let mut a = cargo_process("install foo").build_command(); + let mut b = cargo_process("install bar").build_command(); + + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + assert!(!str::from_utf8(&a.stderr).unwrap().contains(LOCKED_BUILD)); + assert!(!str::from_utf8(&b.stderr).unwrap().contains(LOCKED_BUILD)); + + execs().run_output(&a); + execs().run_output(&b); + + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_installed_exe(paths::cargo_home(), "bar"); +} + +#[cargo_test] +fn one_install_should_be_bad() { + let p = project() + .no_manifest() + .file("a/Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file("a/src/main.rs", "fn main() {}") + .file("b/Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file("b/src/main.rs", "fn main() {}"); + let p = p.build(); + + let mut a = p.cargo("install").cwd("a").build_command(); + let mut b = p.cargo("install").cwd("b").build_command(); + + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + execs().run_output(&a); + execs().run_output(&b); + + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn multiple_registry_fetches() { + let mut pkg = Package::new("bar", "1.0.2"); + for i in 0..10 { + let name = format!("foo{}", i); + Package::new(&name, "1.0.0").publish(); + pkg.dep(&name, "*"); + } + pkg.publish(); + + let p = project() + .no_manifest() + .file( + "a/Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + + [dependencies] + bar = "*" + "#, + ) + .file("a/src/main.rs", "fn main() {}") + .file( + "b/Cargo.toml", + r#" + [package] + name = "bar" + authors = [] + version = "0.0.0" + + [dependencies] + bar = "*" + "#, + ) + .file("b/src/main.rs", "fn main() {}"); + let p = p.build(); + + let mut a = p.cargo("build").cwd("a").build_command(); + let mut b = p.cargo("build").cwd("b").build_command(); + + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + execs().run_output(&a); + execs().run_output(&b); + + let suffix = env::consts::EXE_SUFFIX; + assert!(p + .root() + .join("a/target/debug") + .join(format!("foo{}", suffix)) + .is_file()); + assert!(p + .root() + .join("b/target/debug") + .join(format!("bar{}", suffix)) + .is_file()); +} + +#[cargo_test] +fn git_same_repo_different_tags() { + let a = git::new("dep", |project| { + project + .file("Cargo.toml", &basic_manifest("dep", "0.5.0")) + .file("src/lib.rs", "pub fn tag1() {}") + }); + + let repo = git2::Repository::open(&a.root()).unwrap(); + git::tag(&repo, "tag1"); + + a.change_file("src/lib.rs", "pub fn tag2() {}"); + git::add(&repo); + git::commit(&repo); + git::tag(&repo, "tag2"); + + let p = project() + .no_manifest() + .file( + "a/Cargo.toml", + &format!( + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + + [dependencies] + dep = {{ git = '{}', tag = 'tag1' }} + "#, + a.url() + ), + ) + .file( + "a/src/main.rs", + "extern crate dep; fn main() { dep::tag1(); }", + ) + .file( + "b/Cargo.toml", + &format!( + r#" + [package] + name = "bar" + authors = [] + version = "0.0.0" + + [dependencies] + dep = {{ git = '{}', tag = 'tag2' }} + "#, + a.url() + ), + ) + .file( + "b/src/main.rs", + "extern crate dep; fn main() { dep::tag2(); }", + ); + let p = p.build(); + + let mut a = p.cargo("build -v").cwd("a").build_command(); + let mut b = p.cargo("build -v").cwd("b").build_command(); + + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + execs().run_output(&a); + execs().run_output(&b); +} + +#[cargo_test] +fn git_same_branch_different_revs() { + let a = git::new("dep", |project| { + project + .file("Cargo.toml", &basic_manifest("dep", "0.5.0")) + .file("src/lib.rs", "pub fn f1() {}") + }); + + let p = project() + .no_manifest() + .file( + "a/Cargo.toml", + &format!( + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + + [dependencies] + dep = {{ git = '{}' }} + "#, + a.url() + ), + ) + .file( + "a/src/main.rs", + "extern crate dep; fn main() { dep::f1(); }", + ) + .file( + "b/Cargo.toml", + &format!( + r#" + [package] + name = "bar" + authors = [] + version = "0.0.0" + + [dependencies] + dep = {{ git = '{}' }} + "#, + a.url() + ), + ) + .file( + "b/src/main.rs", + "extern crate dep; fn main() { dep::f2(); }", + ); + let p = p.build(); + + // Generate a Cargo.lock pointing at the current rev, then clear out the + // target directory + p.cargo("build").cwd("a").run(); + fs::remove_dir_all(p.root().join("a/target")).unwrap(); + + // Make a new commit on the master branch + let repo = git2::Repository::open(&a.root()).unwrap(); + a.change_file("src/lib.rs", "pub fn f2() {}"); + git::add(&repo); + git::commit(&repo); + + // Now run both builds in parallel. The build of `b` should pick up the + // newest commit while the build of `a` should use the locked old commit. + let mut a = p.cargo("build").cwd("a").build_command(); + let mut b = p.cargo("build").cwd("b").build_command(); + + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + execs().run_output(&a); + execs().run_output(&b); +} + +#[cargo_test] +fn same_project() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", ""); + let p = p.build(); + + let mut a = p.cargo("build").build_command(); + let mut b = p.cargo("build").build_command(); + + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + execs().run_output(&a); + execs().run_output(&b); +} + +// Make sure that if Cargo dies while holding a lock that it's released and the +// next Cargo to come in will take over cleanly. +#[cargo_test] +fn killing_cargo_releases_the_lock() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + build = "build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + r#" + use std::net::TcpStream; + + fn main() { + if std::env::var("A").is_ok() { + TcpStream::connect(&std::env::var("ADDR").unwrap()[..]) + .unwrap(); + std::thread::sleep(std::time::Duration::new(10, 0)); + } + } + "#, + ); + let p = p.build(); + + // Our build script will connect to our local TCP socket to inform us that + // it's started and that's how we know that `a` will have the lock + // when we kill it. + let l = TcpListener::bind("127.0.0.1:0").unwrap(); + let mut a = p.cargo("build").build_command(); + let mut b = p.cargo("build").build_command(); + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + a.env("ADDR", l.local_addr().unwrap().to_string()) + .env("A", "a"); + b.env("ADDR", l.local_addr().unwrap().to_string()) + .env_remove("A"); + + // Spawn `a`, wait for it to get to the build script (at which point the + // lock is held), then kill it. + let mut a = a.spawn().unwrap(); + l.accept().unwrap(); + a.kill().unwrap(); + + // Spawn `b`, then just finish the output of a/b the same way the above + // tests does. + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + // We killed `a`, so it shouldn't succeed, but `b` should have succeeded. + assert!(!a.status.success()); + execs().run_output(&b); +} + +#[cargo_test] +fn debug_release_ok() { + let p = project().file("src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("build").run(); + fs::remove_dir_all(p.root().join("target")).unwrap(); + + let mut a = p.cargo("build").build_command(); + let mut b = p.cargo("build --release").build_command(); + a.stdout(Stdio::piped()).stderr(Stdio::piped()); + b.stdout(Stdio::piped()).stderr(Stdio::piped()); + let a = a.spawn().unwrap(); + let b = b.spawn().unwrap(); + let a = thread::spawn(move || a.wait_with_output().unwrap()); + let b = b.wait_with_output().unwrap(); + let a = a.join().unwrap(); + + execs() + .with_stderr_data(str![[r#" +... +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run_output(&a); + execs() + .with_stderr_data(str![[r#" +... +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run_output(&b); +} + +#[cargo_test] +fn no_deadlock_with_git_dependencies() { + let dep1 = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file("src/lib.rs", "") + }); + + let dep2 = git::new("dep2", |project| { + project + .file("Cargo.toml", &basic_manifest("dep2", "0.5.0")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + + [dependencies] + dep1 = {{ git = '{}' }} + dep2 = {{ git = '{}' }} + "#, + dep1.url(), + dep2.url() + ), + ) + .file("src/main.rs", "fn main() { }"); + let p = p.build(); + + let n_concurrent_builds = 5; + + let (tx, rx) = channel(); + for _ in 0..n_concurrent_builds { + let cmd = p + .cargo("build") + .build_command() + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn(); + let tx = tx.clone(); + thread::spawn(move || { + let result = cmd.unwrap().wait_with_output().unwrap(); + tx.send(result).unwrap() + }); + } + + for _ in 0..n_concurrent_builds { + let result = rx.recv_timeout(slow_cpu_multiplier(30)).expect("Deadlock!"); + execs().run_output(&result); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config.rs new file mode 100644 index 000000000..80be8dabc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config.rs @@ -0,0 +1,2275 @@ +//! Tests for config settings. + +use std::borrow::Borrow; +use std::collections::{BTreeMap, HashMap}; +use std::fs; +use std::io; +use std::os; +use std::path::{Path, PathBuf}; + +use cargo::core::features::{GitFeatures, GitoxideFeatures}; +use cargo::core::{PackageIdSpec, Shell}; +use cargo::util::auth::RegistryConfig; +use cargo::util::context::{ + self, Definition, GlobalContext, JobsConfig, SslVersionConfig, StringList, +}; +use cargo::CargoResult; +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{paths, project, project_in_home, symlink_supported, t}; +use cargo_util_schemas::manifest::TomlTrimPaths; +use cargo_util_schemas::manifest::TomlTrimPathsValue; +use cargo_util_schemas::manifest::{self as cargo_toml, TomlDebugInfo, VecStringOrBool as VSOB}; +use serde::Deserialize; + +/// Helper for constructing a `GlobalContext` object. +pub struct GlobalContextBuilder { + env: HashMap, + unstable: Vec, + config_args: Vec, + cwd: Option, + root: Option, + enable_nightly_features: bool, +} + +impl GlobalContextBuilder { + pub fn new() -> GlobalContextBuilder { + GlobalContextBuilder { + env: HashMap::new(), + unstable: Vec::new(), + config_args: Vec::new(), + root: None, + cwd: None, + enable_nightly_features: false, + } + } + + /// Passes a `-Z` flag. + pub fn unstable_flag(&mut self, s: impl Into) -> &mut Self { + self.unstable.push(s.into()); + self + } + + /// Sets an environment variable. + pub fn env(&mut self, key: impl Into, val: impl Into) -> &mut Self { + self.env.insert(key.into(), val.into()); + self + } + + /// Unconditionally enable nightly features, even on stable channels. + pub fn nightly_features_allowed(&mut self, allowed: bool) -> &mut Self { + self.enable_nightly_features = allowed; + self + } + + /// Passes a `--config` flag. + pub fn config_arg(&mut self, arg: impl Into) -> &mut Self { + self.config_args.push(arg.into()); + self + } + + /// Sets the current working directory where config files will be loaded. + /// + /// Default is the root from [`GlobalContextBuilder::root`] or [`paths::root`]. + pub fn cwd(&mut self, path: impl AsRef) -> &mut Self { + let path = path.as_ref(); + let cwd = self + .root + .as_ref() + .map_or_else(|| paths::root().join(path), |r| r.join(path)); + self.cwd = Some(cwd); + self + } + + /// Sets the test root directory. + /// + /// This generally should not be necessary. It is only useful if you want + /// to create a [`GlobalContext`] from within a thread. Since Cargo's + /// testsuite uses thread-local storage, this can be used to avoid accessing + /// that thread-local storage. + /// + /// Default is [`paths::root`]. + pub fn root(&mut self, path: impl Into) -> &mut Self { + self.root = Some(path.into()); + self + } + + /// Creates the [`GlobalContext`]. + pub fn build(&self) -> GlobalContext { + self.build_err().unwrap() + } + + /// Creates the [`GlobalContext`], returning a Result. + pub fn build_err(&self) -> CargoResult { + let root = self.root.clone().unwrap_or_else(|| paths::root()); + let output = Box::new(fs::File::create(root.join("shell.out")).unwrap()); + let shell = Shell::from_write(output); + let cwd = self.cwd.clone().unwrap_or_else(|| root.clone()); + let homedir = root.join("home").join(".cargo"); + let mut gctx = GlobalContext::new(shell, cwd, homedir); + gctx.nightly_features_allowed = self.enable_nightly_features || !self.unstable.is_empty(); + gctx.set_env(self.env.clone()); + gctx.set_search_stop_path(&root); + gctx.configure( + 0, + false, + None, + false, + false, + false, + &None, + &self.unstable, + &self.config_args, + )?; + Ok(gctx) + } +} + +fn new_gctx() -> GlobalContext { + GlobalContextBuilder::new().build() +} + +/// Read the output from Config. +pub fn read_output(gctx: GlobalContext) -> String { + drop(gctx); // Paranoid about flushing the file. + let path = paths::root().join("shell.out"); + fs::read_to_string(path).unwrap() +} + +#[cargo_test] +fn read_env_vars_for_config() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + fn main() { + assert_eq!(env::var("NUM_JOBS").unwrap(), "100"); + } + "#, + ) + .build(); + + p.cargo("check").env("CARGO_BUILD_JOBS", "100").run(); +} + +pub fn write_config_extless(config: &str) { + write_config_at(paths::root().join(".cargo/config"), config); +} + +pub fn write_config_at(path: impl AsRef, contents: &str) { + let path = paths::root().join(path.as_ref()); + fs::create_dir_all(path.parent().unwrap()).unwrap(); + fs::write(path, contents).unwrap(); +} + +pub fn write_config_toml(config: &str) { + write_config_at(paths::root().join(".cargo/config.toml"), config); +} + +#[cfg(unix)] +fn symlink_file(target: &Path, link: &Path) -> io::Result<()> { + os::unix::fs::symlink(target, link) +} + +#[cfg(windows)] +fn symlink_file(target: &Path, link: &Path) -> io::Result<()> { + os::windows::fs::symlink_file(target, link) +} + +fn make_config_symlink_to_config_toml_absolute() { + let toml_path = paths::root().join(".cargo/config.toml"); + let symlink_path = paths::root().join(".cargo/config"); + t!(symlink_file(&toml_path, &symlink_path)); +} + +fn make_config_symlink_to_config_toml_relative() { + let symlink_path = paths::root().join(".cargo/config"); + t!(symlink_file(Path::new("config.toml"), &symlink_path)); +} + +fn rename_config_toml_to_config_replacing_with_symlink() { + let root = paths::root(); + t!(fs::rename( + root.join(".cargo/config.toml"), + root.join(".cargo/config") + )); + t!(symlink_file( + Path::new("config"), + &root.join(".cargo/config.toml") + )); +} + +#[track_caller] +pub fn assert_error>(error: E, msgs: impl IntoData) { + let causes = error + .borrow() + .chain() + .enumerate() + .map(|(i, e)| { + if i == 0 { + e.to_string() + } else { + format!("Caused by:\n {}", e) + } + }) + .collect::>() + .join("\n\n"); + assert_e2e().eq(&causes, msgs); +} + +#[cargo_test] +fn get_config() { + write_config_toml( + "\ +[S] +f1 = 123 +", + ); + + let gctx = new_gctx(); + + #[derive(Debug, Deserialize, Eq, PartialEq)] + struct S { + f1: Option, + } + let s: S = gctx.get("S").unwrap(); + assert_eq!(s, S { f1: Some(123) }); + let gctx = GlobalContextBuilder::new().env("CARGO_S_F1", "456").build(); + let s: S = gctx.get("S").unwrap(); + assert_eq!(s, S { f1: Some(456) }); +} + +#[cfg(windows)] +#[cargo_test] +fn environment_variable_casing() { + // Issue #11814: Environment variable names are case-insensitive on Windows. + let gctx = GlobalContextBuilder::new() + .env("Path", "abc") + .env("Two-Words", "abc") + .env("two_words", "def") + .build(); + + let var = gctx.get_env("PATH").unwrap(); + assert_eq!(var, String::from("abc")); + + let var = gctx.get_env("path").unwrap(); + assert_eq!(var, String::from("abc")); + + let var = gctx.get_env("TWO-WORDS").unwrap(); + assert_eq!(var, String::from("abc")); + + // Make sure that we can still distinguish between dashes and underscores + // in variable names. + let var = gctx.get_env("Two_Words").unwrap(); + assert_eq!(var, String::from("def")); +} + +#[cargo_test] +fn config_works_without_extension() { + write_config_extless( + "\ +[foo] +f1 = 1 +", + ); + + let gctx = new_gctx(); + + assert_eq!(gctx.get::>("foo.f1").unwrap(), Some(1)); + + // It should NOT have warned for the symlink. + let output = read_output(gctx); + let expected = str![[r#" +[WARNING] `[ROOT]/.cargo/config` is deprecated in favor of `config.toml` +[NOTE] if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml` + +"#]]; + assert_e2e().eq(&output, expected); +} + +#[cargo_test] +fn home_config_works_without_extension() { + write_config_at( + paths::cargo_home().join("config"), + "\ +[foo] +f1 = 1 +", + ); + let p = project_in_home("foo").file("src/lib.rs", "").build(); + + p.cargo("-vV") + .with_stderr_data(str![[r#" +[WARNING] `[ROOT]/home/.cargo/config` is deprecated in favor of `config.toml` +[NOTE] if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml` + +"#]]) + .run(); +} + +#[cargo_test] +fn config_ambiguous_filename_symlink_doesnt_warn() { + // Windows requires special permissions to create symlinks. + // If we don't have permission, just skip this test. + if !symlink_supported() { + return; + }; + + write_config_toml( + "\ +[foo] +f1 = 1 +", + ); + + make_config_symlink_to_config_toml_absolute(); + + let gctx = new_gctx(); + + assert_eq!(gctx.get::>("foo.f1").unwrap(), Some(1)); + + // It should NOT have warned for the symlink. + let output = read_output(gctx); + assert_e2e().eq(&output, str![[""]]); +} + +#[cargo_test] +fn config_ambiguous_filename_symlink_doesnt_warn_relative() { + // Windows requires special permissions to create symlinks. + // If we don't have permission, just skip this test. + if !symlink_supported() { + return; + }; + + write_config_toml( + "\ +[foo] +f1 = 1 +", + ); + + make_config_symlink_to_config_toml_relative(); + + let gctx = new_gctx(); + + assert_eq!(gctx.get::>("foo.f1").unwrap(), Some(1)); + + // It should NOT have warned for the symlink. + let output = read_output(gctx); + assert_e2e().eq(&output, str![[""]]); +} + +#[cargo_test] +fn config_ambiguous_filename_symlink_doesnt_warn_backward() { + // Windows requires special permissions to create symlinks. + // If we don't have permission, just skip this test. + if !symlink_supported() { + return; + }; + + write_config_toml( + "\ +[foo] +f1 = 1 +", + ); + + rename_config_toml_to_config_replacing_with_symlink(); + + let gctx = new_gctx(); + + assert_eq!(gctx.get::>("foo.f1").unwrap(), Some(1)); + + // It should NOT have warned for this situation. + let output = read_output(gctx); + assert_e2e().eq(&output, str![[""]]); +} + +#[cargo_test] +fn config_ambiguous_filename() { + write_config_extless( + "\ +[foo] +f1 = 1 +", + ); + + write_config_toml( + "\ +[foo] +f1 = 2 +", + ); + + let gctx = new_gctx(); + + // It should use the value from the one without the extension for + // backwards compatibility. + assert_eq!(gctx.get::>("foo.f1").unwrap(), Some(1)); + + // But it also should have warned. + let output = read_output(gctx); + let expected = str![[r#" +[WARNING] both `[ROOT]/.cargo/config` and `[ROOT]/.cargo/config.toml` exist. Using `[ROOT]/.cargo/config` + +"#]]; + assert_e2e().eq(&output, expected); +} + +#[cargo_test] +fn config_unused_fields() { + write_config_toml( + "\ +[S] +unused = 456 +", + ); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_S_UNUSED2", "1") + .env("CARGO_S2_UNUSED", "2") + .build(); + + #[derive(Debug, Deserialize, Eq, PartialEq)] + struct S { + f1: Option, + } + // This prints a warning (verified below). + let s: S = gctx.get("S").unwrap(); + assert_eq!(s, S { f1: None }); + // This does not print anything, we cannot easily/reliably warn for + // environment variables. + let s: S = gctx.get("S2").unwrap(); + assert_eq!(s, S { f1: None }); + + // Verify the warnings. + let output = read_output(gctx); + let expected = str![[r#" +[WARNING] unused config key `S.unused` in `[ROOT]/.cargo/config.toml` + +"#]]; + assert_e2e().eq(&output, expected); +} + +#[cargo_test] +fn config_load_toml_profile() { + write_config_toml( + "\ +[profile.dev] +opt-level = 's' +lto = true +codegen-units=4 +debug = true +debug-assertions = true +rpath = true +panic = 'abort' +overflow-checks = true +incremental = true + +[profile.dev.build-override] +opt-level = 1 + +[profile.dev.package.bar] +codegen-units = 9 + +[profile.no-lto] +inherits = 'dev' +dir-name = 'without-lto' +lto = false +", + ); + + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_PROFILE_DEV_CODEGEN_UNITS", "5") + .env("CARGO_PROFILE_DEV_BUILD_OVERRIDE_CODEGEN_UNITS", "11") + .env("CARGO_PROFILE_DEV_PACKAGE_env_CODEGEN_UNITS", "13") + .env("CARGO_PROFILE_DEV_PACKAGE_bar_OPT_LEVEL", "2") + .build(); + + // TODO: don't use actual `tomlprofile`. + let p: cargo_toml::TomlProfile = gctx.get("profile.dev").unwrap(); + let mut packages = BTreeMap::new(); + let key = + cargo_toml::ProfilePackageSpec::Spec(::cargo::core::PackageIdSpec::parse("bar").unwrap()); + let o_profile = cargo_toml::TomlProfile { + opt_level: Some(cargo_toml::TomlOptLevel("2".to_string())), + codegen_units: Some(9), + ..Default::default() + }; + packages.insert(key, o_profile); + let key = + cargo_toml::ProfilePackageSpec::Spec(::cargo::core::PackageIdSpec::parse("env").unwrap()); + let o_profile = cargo_toml::TomlProfile { + codegen_units: Some(13), + ..Default::default() + }; + packages.insert(key, o_profile); + + assert_eq!( + p, + cargo_toml::TomlProfile { + opt_level: Some(cargo_toml::TomlOptLevel("s".to_string())), + lto: Some(cargo_toml::StringOrBool::Bool(true)), + codegen_units: Some(5), + debug: Some(cargo_toml::TomlDebugInfo::Full), + debug_assertions: Some(true), + rpath: Some(true), + panic: Some("abort".to_string()), + overflow_checks: Some(true), + incremental: Some(true), + package: Some(packages), + build_override: Some(Box::new(cargo_toml::TomlProfile { + opt_level: Some(cargo_toml::TomlOptLevel("1".to_string())), + codegen_units: Some(11), + ..Default::default() + })), + ..Default::default() + } + ); + + let p: cargo_toml::TomlProfile = gctx.get("profile.no-lto").unwrap(); + assert_eq!( + p, + cargo_toml::TomlProfile { + lto: Some(cargo_toml::StringOrBool::Bool(false)), + dir_name: Some(String::from("without-lto")), + inherits: Some(String::from("dev")), + ..Default::default() + } + ); +} + +#[cargo_test] +fn profile_env_var_prefix() { + // Check for a bug with collision on DEBUG vs DEBUG_ASSERTIONS. + let gctx = GlobalContextBuilder::new() + .env("CARGO_PROFILE_DEV_DEBUG_ASSERTIONS", "false") + .build(); + let p: cargo_toml::TomlProfile = gctx.get("profile.dev").unwrap(); + assert_eq!(p.debug_assertions, Some(false)); + assert_eq!(p.debug, None); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_PROFILE_DEV_DEBUG", "1") + .build(); + let p: cargo_toml::TomlProfile = gctx.get("profile.dev").unwrap(); + assert_eq!(p.debug_assertions, None); + assert_eq!(p.debug, Some(cargo_toml::TomlDebugInfo::Limited)); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_PROFILE_DEV_DEBUG_ASSERTIONS", "false") + .env("CARGO_PROFILE_DEV_DEBUG", "1") + .build(); + let p: cargo_toml::TomlProfile = gctx.get("profile.dev").unwrap(); + assert_eq!(p.debug_assertions, Some(false)); + assert_eq!(p.debug, Some(cargo_toml::TomlDebugInfo::Limited)); +} + +#[cargo_test] +fn config_deserialize_any() { + // Some tests to exercise deserialize_any for deserializers that need to + // be told the format. + write_config_toml( + "\ +a = true +b = ['b'] +c = ['c'] +", + ); + + // advanced-env + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_ENVB", "false") + .env("CARGO_C", "['d']") + .env("CARGO_ENVL", "['a', 'b']") + .build(); + assert_eq!(gctx.get::("a").unwrap(), VSOB::Bool(true)); + assert_eq!( + gctx.get::("b").unwrap(), + VSOB::VecString(vec!["b".to_string()]) + ); + assert_eq!( + gctx.get::("c").unwrap(), + VSOB::VecString(vec!["c".to_string(), "d".to_string()]) + ); + assert_eq!(gctx.get::("envb").unwrap(), VSOB::Bool(false)); + assert_eq!( + gctx.get::("envl").unwrap(), + VSOB::VecString(vec!["a".to_string(), "b".to_string()]) + ); + + // Demonstrate where merging logic isn't very smart. This could be improved. + let gctx = GlobalContextBuilder::new().env("CARGO_A", "x y").build(); + assert_error( + gctx.get::("a").unwrap_err(), + "\ +error in environment variable `CARGO_A`: could not load config key `a` + +Caused by: + invalid type: string \"x y\", expected a boolean or vector of strings", + ); + + // Normal env. + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_B", "d e") + .env("CARGO_C", "f g") + .build(); + assert_eq!( + gctx.get::("b").unwrap(), + VSOB::VecString(vec!["b".to_string(), "d".to_string(), "e".to_string()]) + ); + assert_eq!( + gctx.get::("c").unwrap(), + VSOB::VecString(vec!["c".to_string(), "f".to_string(), "g".to_string()]) + ); + + // config-cli + // This test demonstrates that ConfigValue::merge isn't very smart. + // It would be nice if it was smarter. + let gctx = GlobalContextBuilder::new() + .config_arg("a = ['a']") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +failed to merge --config key `a` into `[..]/.cargo/config.toml` + +Caused by: + failed to merge config value from `--config cli option` into `[..]/.cargo/config.toml`: \ +expected boolean, but found array", + ); + + // config-cli and advanced-env + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .config_arg("b=['clib']") + .config_arg("c=['clic']") + .env("CARGO_B", "env1 env2") + .env("CARGO_C", "['e1', 'e2']") + .build(); + assert_eq!( + gctx.get::("b").unwrap(), + VSOB::VecString(vec![ + "b".to_string(), + "env1".to_string(), + "env2".to_string(), + "clib".to_string(), + ]) + ); + assert_eq!( + gctx.get::("c").unwrap(), + VSOB::VecString(vec![ + "c".to_string(), + "e1".to_string(), + "e2".to_string(), + "clic".to_string(), + ]) + ); +} + +#[cargo_test] +fn config_toml_errors() { + write_config_toml( + "\ +[profile.dev] +opt-level = 'foo' +", + ); + + let gctx = new_gctx(); + + assert_error( + gctx.get::("profile.dev") + .unwrap_err(), + "\ +error in [..]/.cargo/config.toml: could not load config key `profile.dev.opt-level` + +Caused by: + must be `0`, `1`, `2`, `3`, `s` or `z`, but found the string: \"foo\"", + ); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_PROFILE_DEV_OPT_LEVEL", "asdf") + .build(); + + assert_error( + gctx.get::("profile.dev").unwrap_err(), + "\ +error in environment variable `CARGO_PROFILE_DEV_OPT_LEVEL`: could not load config key `profile.dev.opt-level` + +Caused by: + must be `0`, `1`, `2`, `3`, `s` or `z`, but found the string: \"asdf\"", + ); +} + +#[cargo_test] +fn load_nested() { + write_config_toml( + "\ +[nest.foo] +f1 = 1 +f2 = 2 +[nest.bar] +asdf = 3 +", + ); + + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_NEST_foo_f2", "3") + .env("CARGO_NESTE_foo_f1", "1") + .env("CARGO_NESTE_foo_f2", "3") + .env("CARGO_NESTE_bar_asdf", "3") + .build(); + + type Nested = HashMap>; + + let n: Nested = gctx.get("nest").unwrap(); + let mut expected = HashMap::new(); + let mut foo = HashMap::new(); + foo.insert("f1".to_string(), 1); + foo.insert("f2".to_string(), 3); + expected.insert("foo".to_string(), foo); + let mut bar = HashMap::new(); + bar.insert("asdf".to_string(), 3); + expected.insert("bar".to_string(), bar); + assert_eq!(n, expected); + + let n: Nested = gctx.get("neste").unwrap(); + assert_eq!(n, expected); +} + +#[cargo_test] +fn get_errors() { + write_config_toml( + "\ +[S] +f1 = 123 +f2 = 'asdf' +big = 123456789 +", + ); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_E_S", "asdf") + .env("CARGO_E_BIG", "123456789") + .build(); + assert_error( + gctx.get::("foo").unwrap_err(), + "missing config key `foo`", + ); + assert_error( + gctx.get::("foo.bar").unwrap_err(), + "missing config key `foo.bar`", + ); + assert_error( + gctx.get::("S.f2").unwrap_err(), + "error in [..]/.cargo/config.toml: `S.f2` expected an integer, but found a string", + ); + assert_error( + gctx.get::("S.big").unwrap_err(), + "\ +error in [..].cargo/config.toml: could not load config key `S.big` + +Caused by: + invalid value: integer `123456789`, expected u8", + ); + + // Environment variable type errors. + assert_error( + gctx.get::("e.s").unwrap_err(), + "error in environment variable `CARGO_E_S`: invalid digit found in string", + ); + assert_error( + gctx.get::("e.big").unwrap_err(), + "\ +error in environment variable `CARGO_E_BIG`: could not load config key `e.big` + +Caused by: + invalid value: integer `123456789`, expected i8", + ); + + #[derive(Debug, Deserialize)] + #[allow(dead_code)] + struct S { + f1: i64, + f2: String, + f3: i64, + big: i64, + } + assert_error(gctx.get::("S").unwrap_err(), "missing field `f3`"); +} + +#[cargo_test] +fn config_get_option() { + write_config_toml( + "\ +[foo] +f1 = 1 +", + ); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_BAR_ASDF", "3") + .build(); + + assert_eq!(gctx.get::>("a").unwrap(), None); + assert_eq!(gctx.get::>("a.b").unwrap(), None); + assert_eq!(gctx.get::>("foo.f1").unwrap(), Some(1)); + assert_eq!(gctx.get::>("bar.asdf").unwrap(), Some(3)); + assert_eq!(gctx.get::>("bar.zzzz").unwrap(), None); +} + +#[cargo_test] +fn config_bad_toml() { + write_config_toml("asdf"); + let gctx = new_gctx(); + assert_error( + gctx.get::("foo").unwrap_err(), + "\ +could not load Cargo configuration + +Caused by: + could not parse TOML configuration in `[..]/.cargo/config.toml` + +Caused by: + TOML parse error at line 1, column 5 + | +1 | asdf + | ^ +expected `.`, `=` +", + ); +} + +#[cargo_test] +fn config_get_list() { + write_config_toml( + "\ +l1 = [] +l2 = ['one', 'two'] +l3 = 123 +l4 = ['one', 'two'] + +[nested] +l = ['x'] + +[nested2] +l = ['y'] + +[nested-empty] +", + ); + + type L = Vec; + + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_L4", "['three', 'four']") + .env("CARGO_L5", "['a']") + .env("CARGO_ENV_EMPTY", "[]") + .env("CARGO_ENV_BLANK", "") + .env("CARGO_ENV_NUM", "1") + .env("CARGO_ENV_NUM_LIST", "[1]") + .env("CARGO_ENV_TEXT", "asdf") + .env("CARGO_LEPAIR", "['a', 'b']") + .env("CARGO_NESTED2_L", "['z']") + .env("CARGO_NESTEDE_L", "['env']") + .env("CARGO_BAD_ENV", "[zzz]") + .build(); + + assert_eq!(gctx.get::("unset").unwrap(), vec![] as Vec); + assert_eq!(gctx.get::("l1").unwrap(), vec![] as Vec); + assert_eq!(gctx.get::("l2").unwrap(), vec!["one", "two"]); + assert_error( + gctx.get::("l3").unwrap_err(), + "\ +invalid configuration for key `l3` +expected a list, but found a integer for `l3` in [..]/.cargo/config.toml", + ); + assert_eq!( + gctx.get::("l4").unwrap(), + vec!["one", "two", "three", "four"] + ); + assert_eq!(gctx.get::("l5").unwrap(), vec!["a"]); + assert_eq!(gctx.get::("env-empty").unwrap(), vec![] as Vec); + assert_eq!(gctx.get::("env-blank").unwrap(), vec![] as Vec); + assert_eq!(gctx.get::("env-num").unwrap(), vec!["1".to_string()]); + assert_error( + gctx.get::("env-num-list").unwrap_err(), + "error in environment variable `CARGO_ENV_NUM_LIST`: \ + expected string, found integer", + ); + assert_eq!(gctx.get::("env-text").unwrap(), vec!["asdf".to_string()]); + // "invalid number" here isn't the best error, but I think it's just toml.rs. + assert_error( + gctx.get::("bad-env").unwrap_err(), + "\ +error in environment variable `CARGO_BAD_ENV`: could not parse TOML list: TOML parse error at line 1, column 2 + | +1 | [zzz] + | ^ +invalid array +expected `]` +", + ); + + // Try some other sequence-like types. + assert_eq!( + gctx.get::<(String, String, String, String)>("l4").unwrap(), + ( + "one".to_string(), + "two".to_string(), + "three".to_string(), + "four".to_string() + ) + ); + assert_eq!(gctx.get::<(String,)>("l5").unwrap(), ("a".to_string(),)); + + // Tuple struct + #[derive(Debug, Deserialize, Eq, PartialEq)] + struct TupS(String, String); + assert_eq!( + gctx.get::("lepair").unwrap(), + TupS("a".to_string(), "b".to_string()) + ); + + // Nested with an option. + #[derive(Debug, Deserialize, Eq, PartialEq)] + struct S { + l: Option>, + } + assert_eq!(gctx.get::("nested-empty").unwrap(), S { l: None }); + assert_eq!( + gctx.get::("nested").unwrap(), + S { + l: Some(vec!["x".to_string()]), + } + ); + assert_eq!( + gctx.get::("nested2").unwrap(), + S { + l: Some(vec!["y".to_string(), "z".to_string()]), + } + ); + assert_eq!( + gctx.get::("nestede").unwrap(), + S { + l: Some(vec!["env".to_string()]), + } + ); +} + +#[cargo_test] +fn config_get_other_types() { + write_config_toml( + "\ +ns = 123 +ns2 = 456 +", + ); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_NSE", "987") + .env("CARGO_NS2", "654") + .build(); + + #[derive(Debug, Deserialize, Eq, PartialEq)] + #[serde(transparent)] + struct NewS(i32); + assert_eq!(gctx.get::("ns").unwrap(), NewS(123)); + assert_eq!(gctx.get::("ns2").unwrap(), NewS(654)); + assert_eq!(gctx.get::("nse").unwrap(), NewS(987)); + assert_error( + gctx.get::("unset").unwrap_err(), + "missing config key `unset`", + ); +} + +#[cargo_test] +fn config_relative_path() { + write_config_toml(&format!( + "\ +p1 = 'foo/bar' +p2 = '../abc' +p3 = 'b/c' +abs = '{}' +", + paths::home().display(), + )); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_EPATH", "a/b") + .env("CARGO_P3", "d/e") + .build(); + + assert_eq!( + gctx.get::("p1") + .unwrap() + .resolve_path(&gctx), + paths::root().join("foo/bar") + ); + assert_eq!( + gctx.get::("p2") + .unwrap() + .resolve_path(&gctx), + paths::root().join("../abc") + ); + assert_eq!( + gctx.get::("p3") + .unwrap() + .resolve_path(&gctx), + paths::root().join("d/e") + ); + assert_eq!( + gctx.get::("abs") + .unwrap() + .resolve_path(&gctx), + paths::home() + ); + assert_eq!( + gctx.get::("epath") + .unwrap() + .resolve_path(&gctx), + paths::root().join("a/b") + ); +} + +#[cargo_test] +fn config_get_integers() { + write_config_toml( + "\ +npos = 123456789 +nneg = -123456789 +i64max = 9223372036854775807 +", + ); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_EPOS", "123456789") + .env("CARGO_ENEG", "-1") + .env("CARGO_EI64MAX", "9223372036854775807") + .build(); + + assert_eq!( + gctx.get::("i64max").unwrap(), + 9_223_372_036_854_775_807 + ); + assert_eq!( + gctx.get::("i64max").unwrap(), + 9_223_372_036_854_775_807 + ); + assert_eq!( + gctx.get::("ei64max").unwrap(), + 9_223_372_036_854_775_807 + ); + assert_eq!( + gctx.get::("ei64max").unwrap(), + 9_223_372_036_854_775_807 + ); + + assert_error( + gctx.get::("nneg").unwrap_err(), + "\ +error in [..].cargo/config.toml: could not load config key `nneg` + +Caused by: + invalid value: integer `-123456789`, expected u32", + ); + assert_error( + gctx.get::("eneg").unwrap_err(), + "\ +error in environment variable `CARGO_ENEG`: could not load config key `eneg` + +Caused by: + invalid value: integer `-1`, expected u32", + ); + assert_error( + gctx.get::("npos").unwrap_err(), + "\ +error in [..].cargo/config.toml: could not load config key `npos` + +Caused by: + invalid value: integer `123456789`, expected i8", + ); + assert_error( + gctx.get::("epos").unwrap_err(), + "\ +error in environment variable `CARGO_EPOS`: could not load config key `epos` + +Caused by: + invalid value: integer `123456789`, expected i8", + ); +} + +#[cargo_test] +fn config_get_ssl_version_missing() { + write_config_toml( + "\ +[http] +hello = 'world' +", + ); + + let gctx = new_gctx(); + + assert!(gctx + .get::>("http.ssl-version") + .unwrap() + .is_none()); +} + +#[cargo_test] +fn config_get_ssl_version_single() { + write_config_toml( + "\ +[http] +ssl-version = 'tlsv1.2' +", + ); + + let gctx = new_gctx(); + + let a = gctx + .get::>("http.ssl-version") + .unwrap() + .unwrap(); + match a { + SslVersionConfig::Single(v) => assert_eq!(&v, "tlsv1.2"), + SslVersionConfig::Range(_) => panic!("Did not expect ssl version min/max."), + }; +} + +#[cargo_test] +fn config_get_ssl_version_min_max() { + write_config_toml( + "\ +[http] +ssl-version.min = 'tlsv1.2' +ssl-version.max = 'tlsv1.3' +", + ); + + let gctx = new_gctx(); + + let a = gctx + .get::>("http.ssl-version") + .unwrap() + .unwrap(); + match a { + SslVersionConfig::Single(_) => panic!("Did not expect exact ssl version."), + SslVersionConfig::Range(range) => { + assert_eq!(range.min, Some(String::from("tlsv1.2"))); + assert_eq!(range.max, Some(String::from("tlsv1.3"))); + } + }; +} + +#[cargo_test] +fn config_get_ssl_version_both_forms_configured() { + // this is not allowed + write_config_toml( + "\ +[http] +ssl-version = 'tlsv1.1' +ssl-version.min = 'tlsv1.2' +ssl-version.max = 'tlsv1.3' +", + ); + + let gctx = new_gctx(); + + assert_error( + gctx.get::("http.ssl-version") + .unwrap_err(), + "\ +could not load Cargo configuration + +Caused by: + could not parse TOML configuration in `[..]/.cargo/config.toml` + +Caused by: + TOML parse error at line 3, column 1 + | +3 | ssl-version.min = 'tlsv1.2' + | ^ +dotted key `ssl-version` attempted to extend non-table type (string) +", + ); +} + +#[cargo_test] +/// Assert that unstable options can be configured with the `unstable` table in +/// cargo config files +fn unstable_table_notation() { + write_config_toml( + "\ +[unstable] +print-im-a-teapot = true +", + ); + let gctx = GlobalContextBuilder::new() + .nightly_features_allowed(true) + .build(); + assert_eq!(gctx.cli_unstable().print_im_a_teapot, true); +} + +#[cargo_test] +/// Assert that dotted notation works for configuring unstable options +fn unstable_dotted_notation() { + write_config_toml( + "\ +unstable.print-im-a-teapot = true +", + ); + let gctx = GlobalContextBuilder::new() + .nightly_features_allowed(true) + .build(); + assert_eq!(gctx.cli_unstable().print_im_a_teapot, true); +} + +#[cargo_test] +/// Assert that Zflags on the CLI take precedence over those from config +fn unstable_cli_precedence() { + write_config_toml( + "\ +unstable.print-im-a-teapot = true +", + ); + let gctx = GlobalContextBuilder::new() + .nightly_features_allowed(true) + .build(); + assert_eq!(gctx.cli_unstable().print_im_a_teapot, true); + + let gctx = GlobalContextBuilder::new() + .unstable_flag("print-im-a-teapot=no") + .build(); + assert_eq!(gctx.cli_unstable().print_im_a_teapot, false); +} + +#[cargo_test] +/// Assert that attempting to set an unstable flag that doesn't exist via config +/// is ignored on stable +fn unstable_invalid_flag_ignored_on_stable() { + write_config_toml( + "\ +unstable.an-invalid-flag = 'yes' +", + ); + assert!(GlobalContextBuilder::new().build_err().is_ok()); +} + +#[cargo_test] +/// Assert that unstable options can be configured with the `unstable` table in +/// cargo config files +fn unstable_flags_ignored_on_stable() { + write_config_toml( + "\ +[unstable] +print-im-a-teapot = true +", + ); + // Enforce stable channel even when testing on nightly. + let gctx = GlobalContextBuilder::new() + .nightly_features_allowed(false) + .build(); + assert_eq!(gctx.cli_unstable().print_im_a_teapot, false); +} + +#[cargo_test] +fn table_merge_failure() { + // Config::merge fails to merge entries in two tables. + write_config_at( + "foo/.cargo/config.toml", + " + [table] + key = ['foo'] + ", + ); + write_config_at( + ".cargo/config.toml", + " + [table] + key = 'bar' + ", + ); + + #[derive(Debug, Deserialize)] + #[allow(dead_code)] + struct Table { + key: StringList, + } + let gctx = GlobalContextBuilder::new().cwd("foo").build(); + assert_error( + gctx.get::("table").unwrap_err(), + "\ +could not load Cargo configuration + +Caused by: + failed to merge configuration at `[..]/.cargo/config.toml` + +Caused by: + failed to merge key `table` between [..]/foo/.cargo/config.toml and [..]/.cargo/config.toml + +Caused by: + failed to merge key `key` between [..]/foo/.cargo/config.toml and [..]/.cargo/config.toml + +Caused by: + failed to merge config value from `[..]/.cargo/config.toml` into `[..]/foo/.cargo/config.toml`: \ + expected array, but found string", + ); +} + +#[cargo_test] +fn non_string_in_array() { + // Currently only strings are supported. + write_config_toml("foo = [1, 2, 3]"); + let gctx = new_gctx(); + assert_error( + gctx.get::>("foo").unwrap_err(), + "\ +could not load Cargo configuration + +Caused by: + failed to load TOML configuration from `[..]/.cargo/config.toml` + +Caused by: + failed to parse key `foo` + +Caused by: + expected string but found integer in list", + ); +} + +#[cargo_test] +fn struct_with_opt_inner_struct() { + // Struct with a key that is Option of another struct. + // Check that can be defined with environment variable. + #[derive(Deserialize)] + struct Inner { + value: Option, + } + #[derive(Deserialize)] + struct Foo { + inner: Option, + } + let gctx = GlobalContextBuilder::new() + .env("CARGO_FOO_INNER_VALUE", "12") + .build(); + let f: Foo = gctx.get("foo").unwrap(); + assert_eq!(f.inner.unwrap().value.unwrap(), 12); +} + +#[cargo_test] +fn struct_with_default_inner_struct() { + // Struct with serde defaults. + // Check that can be defined with environment variable. + #[derive(Deserialize, Default)] + #[serde(default)] + struct Inner { + value: i32, + } + #[derive(Deserialize, Default)] + #[serde(default)] + struct Foo { + inner: Inner, + } + let gctx = GlobalContextBuilder::new() + .env("CARGO_FOO_INNER_VALUE", "12") + .build(); + let f: Foo = gctx.get("foo").unwrap(); + assert_eq!(f.inner.value, 12); +} + +#[cargo_test] +fn overlapping_env_config() { + // Issue where one key is a prefix of another. + #[derive(Deserialize)] + #[serde(rename_all = "kebab-case")] + struct Ambig { + debug: Option, + debug_assertions: Option, + } + let gctx = GlobalContextBuilder::new() + .env("CARGO_AMBIG_DEBUG_ASSERTIONS", "true") + .build(); + + let s: Ambig = gctx.get("ambig").unwrap(); + assert_eq!(s.debug_assertions, Some(true)); + assert_eq!(s.debug, None); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_AMBIG_DEBUG", "0") + .build(); + let s: Ambig = gctx.get("ambig").unwrap(); + assert_eq!(s.debug_assertions, None); + assert_eq!(s.debug, Some(0)); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_AMBIG_DEBUG", "1") + .env("CARGO_AMBIG_DEBUG_ASSERTIONS", "true") + .build(); + let s: Ambig = gctx.get("ambig").unwrap(); + assert_eq!(s.debug_assertions, Some(true)); + assert_eq!(s.debug, Some(1)); +} + +#[cargo_test] +fn overlapping_env_with_defaults_errors_out() { + // Issue where one key is a prefix of another. + // This is a limitation of mapping environment variables on to a hierarchy. + // Check that we error out when we hit ambiguity in this way, rather than + // the more-surprising defaulting through. + // If, in the future, we can handle this more correctly, feel free to delete + // this test. + #[derive(Deserialize, Default)] + #[serde(default, rename_all = "kebab-case")] + struct Ambig { + debug: u32, + debug_assertions: bool, + } + let gctx = GlobalContextBuilder::new() + .env("CARGO_AMBIG_DEBUG_ASSERTIONS", "true") + .build(); + let err = gctx.get::("ambig").err().unwrap(); + assert!(format!("{}", err).contains("missing config key `ambig.debug`")); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_AMBIG_DEBUG", "5") + .build(); + let s: Ambig = gctx.get("ambig").unwrap(); + assert_eq!(s.debug_assertions, bool::default()); + assert_eq!(s.debug, 5); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_AMBIG_DEBUG", "1") + .env("CARGO_AMBIG_DEBUG_ASSERTIONS", "true") + .build(); + let s: Ambig = gctx.get("ambig").unwrap(); + assert_eq!(s.debug_assertions, true); + assert_eq!(s.debug, 1); +} + +#[cargo_test] +fn struct_with_overlapping_inner_struct_and_defaults() { + // Struct with serde defaults. + // Check that can be defined with environment variable. + #[derive(Deserialize, Default)] + #[serde(default)] + struct Inner { + value: i32, + } + + // Containing struct with a prefix of inner + // + // This is a limitation of mapping environment variables on to a hierarchy. + // Check that we error out when we hit ambiguity in this way, rather than + // the more-surprising defaulting through. + // If, in the future, we can handle this more correctly, feel free to delete + // this case. + #[derive(Deserialize, Default)] + struct PrefixContainer { + inn: bool, + inner: Inner, + } + let gctx = GlobalContextBuilder::new() + .env("CARGO_PREFIXCONTAINER_INNER_VALUE", "12") + .build(); + let err = gctx + .get::("prefixcontainer") + .err() + .unwrap(); + assert!(format!("{}", err).contains("missing field `inn`")); + let gctx = GlobalContextBuilder::new() + .env("CARGO_PREFIXCONTAINER_INNER_VALUE", "12") + .env("CARGO_PREFIXCONTAINER_INN", "true") + .build(); + let f: PrefixContainer = gctx.get("prefixcontainer").unwrap(); + assert_eq!(f.inner.value, 12); + assert_eq!(f.inn, true); + + // Use default attribute of serde, then we can skip setting the inn field + #[derive(Deserialize, Default)] + #[serde(default)] + struct PrefixContainerFieldDefault { + inn: bool, + inner: Inner, + } + let gctx = GlobalContextBuilder::new() + .env("CARGO_PREFIXCONTAINER_INNER_VALUE", "12") + .build(); + let f = gctx + .get::("prefixcontainer") + .unwrap(); + assert_eq!(f.inner.value, 12); + assert_eq!(f.inn, false); + + // Containing struct where the inner value's field is a prefix of another + // + // This is a limitation of mapping environment variables on to a hierarchy. + // Check that we error out when we hit ambiguity in this way, rather than + // the more-surprising defaulting through. + // If, in the future, we can handle this more correctly, feel free to delete + // this case. + #[derive(Deserialize, Default)] + #[serde(default)] + struct InversePrefixContainer { + inner_field: bool, + inner: Inner, + } + let gctx = GlobalContextBuilder::new() + .env("CARGO_INVERSEPREFIXCONTAINER_INNER_VALUE", "12") + .build(); + let f: InversePrefixContainer = gctx.get("inverseprefixcontainer").unwrap(); + assert_eq!(f.inner_field, bool::default()); + assert_eq!(f.inner.value, 12); +} + +#[cargo_test] +fn string_list_tricky_env() { + // Make sure StringList handles typed env values. + let gctx = GlobalContextBuilder::new() + .env("CARGO_KEY1", "123") + .env("CARGO_KEY2", "true") + .env("CARGO_KEY3", "1 2") + .build(); + let x = gctx.get::("key1").unwrap(); + assert_eq!(x.as_slice(), &["123".to_string()]); + let x = gctx.get::("key2").unwrap(); + assert_eq!(x.as_slice(), &["true".to_string()]); + let x = gctx.get::("key3").unwrap(); + assert_eq!(x.as_slice(), &["1".to_string(), "2".to_string()]); +} + +#[cargo_test] +fn string_list_wrong_type() { + // What happens if StringList is given then wrong type. + write_config_toml("some_list = 123"); + let gctx = GlobalContextBuilder::new().build(); + assert_error( + gctx.get::("some_list").unwrap_err(), + "\ +invalid configuration for key `some_list` +expected a string or array of strings, but found a integer for `some_list` in [..]/.cargo/config.toml", + ); + + write_config_toml("some_list = \"1 2\""); + let gctx = GlobalContextBuilder::new().build(); + let x = gctx.get::("some_list").unwrap(); + assert_eq!(x.as_slice(), &["1".to_string(), "2".to_string()]); +} + +#[cargo_test] +fn string_list_advanced_env() { + // StringList with advanced env. + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_KEY1", "[]") + .env("CARGO_KEY2", "['1 2', '3']") + .env("CARGO_KEY3", "[123]") + .build(); + let x = gctx.get::("key1").unwrap(); + assert_eq!(x.as_slice(), &[] as &[String]); + let x = gctx.get::("key2").unwrap(); + assert_eq!(x.as_slice(), &["1 2".to_string(), "3".to_string()]); + assert_error( + gctx.get::("key3").unwrap_err(), + "error in environment variable `CARGO_KEY3`: expected string, found integer", + ); +} + +#[cargo_test] +fn parse_strip_with_string() { + write_config_toml( + "\ +[profile.release] +strip = 'debuginfo' +", + ); + + let gctx = new_gctx(); + + let p: cargo_toml::TomlProfile = gctx.get("profile.release").unwrap(); + let strip = p.strip.unwrap(); + assert_eq!( + strip, + cargo_toml::StringOrBool::String("debuginfo".to_string()) + ); +} + +#[cargo_test] +fn cargo_target_empty_cfg() { + write_config_toml( + "\ +[build] +target-dir = '' +", + ); + + let gctx = new_gctx(); + + assert_error( + gctx.target_dir().unwrap_err(), + "the target directory is set to an empty string in [..]/.cargo/config.toml", + ); +} + +#[cargo_test] +fn cargo_target_empty_env() { + let project = project().build(); + + project.cargo("check") + .env("CARGO_TARGET_DIR", "") + .with_stderr_data(str![[r#" +[ERROR] the target directory is set to an empty string in the `CARGO_TARGET_DIR` environment variable + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn all_profile_options() { + // Check that all profile options can be serialized/deserialized. + let base_settings = cargo_toml::TomlProfile { + opt_level: Some(cargo_toml::TomlOptLevel("0".to_string())), + lto: Some(cargo_toml::StringOrBool::String("thin".to_string())), + codegen_backend: Some(String::from("example")), + codegen_units: Some(123), + debug: Some(cargo_toml::TomlDebugInfo::Limited), + split_debuginfo: Some("packed".to_string()), + debug_assertions: Some(true), + rpath: Some(true), + panic: Some("abort".to_string()), + overflow_checks: Some(true), + incremental: Some(true), + dir_name: Some(String::from("dir_name")), + inherits: Some(String::from("debug")), + strip: Some(cargo_toml::StringOrBool::String("symbols".to_string())), + package: None, + build_override: None, + rustflags: None, + trim_paths: None, + }; + let mut overrides = BTreeMap::new(); + let key = cargo_toml::ProfilePackageSpec::Spec(PackageIdSpec::parse("foo").unwrap()); + overrides.insert(key, base_settings.clone()); + let profile = cargo_toml::TomlProfile { + build_override: Some(Box::new(base_settings.clone())), + package: Some(overrides), + ..base_settings + }; + let profile_toml = toml::to_string(&profile).unwrap(); + let roundtrip: cargo_toml::TomlProfile = toml::from_str(&profile_toml).unwrap(); + let roundtrip_toml = toml::to_string(&roundtrip).unwrap(); + assert_e2e().eq(&roundtrip_toml, &profile_toml); +} + +#[cargo_test] +fn value_in_array() { + // Value in an array should work + let root_path = paths::root().join(".cargo/config.toml"); + write_config_at( + &root_path, + "\ +[net.ssh] +known-hosts = [ + \"example.com ...\", + \"example.net ...\", +] +", + ); + + let foo_path = paths::root().join("foo/.cargo/config.toml"); + write_config_at( + &foo_path, + "\ +[net.ssh] +known-hosts = [ + \"example.org ...\", +] +", + ); + + let gctx = GlobalContextBuilder::new() + .cwd("foo") + // environment variables don't actually work for known-hosts due to + // space splitting, but this is included here just to validate that + // they work (particularly if other Vec config vars are added + // in the future). + .env("CARGO_NET_SSH_KNOWN_HOSTS", "env-example") + .build(); + let net_config = gctx.net_config().unwrap(); + let kh = net_config + .ssh + .as_ref() + .unwrap() + .known_hosts + .as_ref() + .unwrap(); + assert_eq!(kh.len(), 4); + 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.org ..."); + assert_eq!(kh[2].definition, Definition::Path(foo_path.clone())); + assert_eq!(kh[3].val, "env-example"); + assert_eq!( + kh[3].definition, + Definition::Environment("CARGO_NET_SSH_KNOWN_HOSTS".to_string()) + ); +} + +#[cargo_test] +fn debuginfo_parsing() { + let gctx = GlobalContextBuilder::new().build(); + let p: cargo_toml::TomlProfile = gctx.get("profile.dev").unwrap(); + assert_eq!(p.debug, None); + + let env_test_cases = [ + (TomlDebugInfo::None, ["false", "0", "none"].as_slice()), + (TomlDebugInfo::LineDirectivesOnly, &["line-directives-only"]), + (TomlDebugInfo::LineTablesOnly, &["line-tables-only"]), + (TomlDebugInfo::Limited, &["1", "limited"]), + (TomlDebugInfo::Full, &["true", "2", "full"]), + ]; + for (expected, config_strs) in env_test_cases { + for &val in config_strs { + let gctx = GlobalContextBuilder::new() + .env("CARGO_PROFILE_DEV_DEBUG", val) + .build(); + let debug: TomlDebugInfo = gctx.get("profile.dev.debug").unwrap(); + assert_eq!(debug, expected, "failed to parse {val}"); + } + } + + let toml_test_cases = [ + (TomlDebugInfo::None, ["false", "0", "\"none\""].as_slice()), + ( + TomlDebugInfo::LineDirectivesOnly, + &["\"line-directives-only\""], + ), + (TomlDebugInfo::LineTablesOnly, &["\"line-tables-only\""]), + (TomlDebugInfo::Limited, &["1", "\"limited\""]), + (TomlDebugInfo::Full, &["true", "2", "\"full\""]), + ]; + for (expected, config_strs) in toml_test_cases { + for &val in config_strs { + let gctx = GlobalContextBuilder::new() + .config_arg(format!("profile.dev.debug={val}")) + .build(); + let debug: TomlDebugInfo = gctx.get("profile.dev.debug").unwrap(); + assert_eq!(debug, expected, "failed to parse {val}"); + } + } + + let toml_err_cases = ["\"\"", "\"unrecognized\"", "3"]; + for err_val in toml_err_cases { + let gctx = GlobalContextBuilder::new() + .config_arg(format!("profile.dev.debug={err_val}")) + .build(); + let err = gctx.get::("profile.dev.debug").unwrap_err(); + assert!(err + .to_string() + .ends_with("could not load config key `profile.dev.debug`")); + } +} + +#[cargo_test] +fn build_jobs_missing() { + write_config_toml( + "\ +[build] +", + ); + + let gctx = new_gctx(); + + assert!(gctx + .get::>("build.jobs") + .unwrap() + .is_none()); +} + +#[cargo_test] +fn build_jobs_default() { + write_config_toml( + "\ +[build] +jobs = \"default\" +", + ); + + let gctx = new_gctx(); + + let a = gctx + .get::>("build.jobs") + .unwrap() + .unwrap(); + + match a { + JobsConfig::String(v) => assert_eq!(&v, "default"), + JobsConfig::Integer(_) => panic!("Did not except an integer."), + } +} + +#[cargo_test] +fn build_jobs_integer() { + write_config_toml( + "\ +[build] +jobs = 2 +", + ); + + let gctx = new_gctx(); + + let a = gctx + .get::>("build.jobs") + .unwrap() + .unwrap(); + + match a { + JobsConfig::String(_) => panic!("Did not except an integer."), + JobsConfig::Integer(v) => assert_eq!(v, 2), + } +} + +#[cargo_test] +fn trim_paths_parsing() { + let gctx = GlobalContextBuilder::new().build(); + let p: cargo_toml::TomlProfile = gctx.get("profile.dev").unwrap(); + assert_eq!(p.trim_paths, None); + + let test_cases = [ + (TomlTrimPathsValue::Diagnostics.into(), "diagnostics"), + (TomlTrimPathsValue::Macro.into(), "macro"), + (TomlTrimPathsValue::Object.into(), "object"), + ]; + for (expected, val) in test_cases { + // env + let gctx = GlobalContextBuilder::new() + .env("CARGO_PROFILE_DEV_TRIM_PATHS", val) + .build(); + let trim_paths: TomlTrimPaths = gctx.get("profile.dev.trim-paths").unwrap(); + assert_eq!(trim_paths, expected, "failed to parse {val}"); + + // config.toml + let gctx = GlobalContextBuilder::new() + .config_arg(format!("profile.dev.trim-paths='{val}'")) + .build(); + let trim_paths: TomlTrimPaths = gctx.get("profile.dev.trim-paths").unwrap(); + assert_eq!(trim_paths, expected, "failed to parse {val}"); + } + + let test_cases = [(TomlTrimPaths::none(), false), (TomlTrimPaths::All, true)]; + + for (expected, val) in test_cases { + // env + let gctx = GlobalContextBuilder::new() + .env("CARGO_PROFILE_DEV_TRIM_PATHS", format!("{val}")) + .build(); + let trim_paths: TomlTrimPaths = gctx.get("profile.dev.trim-paths").unwrap(); + assert_eq!(trim_paths, expected, "failed to parse {val}"); + + // config.toml + let gctx = GlobalContextBuilder::new() + .config_arg(format!("profile.dev.trim-paths={val}")) + .build(); + let trim_paths: TomlTrimPaths = gctx.get("profile.dev.trim-paths").unwrap(); + assert_eq!(trim_paths, expected, "failed to parse {val}"); + } + + let expected = vec![ + TomlTrimPathsValue::Diagnostics, + TomlTrimPathsValue::Macro, + TomlTrimPathsValue::Object, + ] + .into(); + let val = r#"["diagnostics", "macro", "object"]"#; + // config.toml + let gctx = GlobalContextBuilder::new() + .config_arg(format!("profile.dev.trim-paths={val}")) + .build(); + let trim_paths: TomlTrimPaths = gctx.get("profile.dev.trim-paths").unwrap(); + assert_eq!(trim_paths, expected, "failed to parse {val}"); +} + +#[cargo_test] +fn missing_fields() { + #[derive(Deserialize, Default, Debug)] + struct Foo { + bar: Bar, + } + + #[derive(Deserialize, Default, Debug)] + struct Bar { + bax: bool, + baz: bool, + } + + let gctx = GlobalContextBuilder::new() + .env("CARGO_FOO_BAR_BAZ", "true") + .build(); + assert_error( + gctx.get::("foo").unwrap_err(), + "\ +could not load config key `foo.bar` + +Caused by: + missing field `bax`", + ); + let gctx: GlobalContext = GlobalContextBuilder::new() + .env("CARGO_FOO_BAR_BAZ", "true") + .env("CARGO_FOO_BAR_BAX", "true") + .build(); + let foo = gctx.get::("foo").unwrap(); + assert_eq!(foo.bar.bax, true); + assert_eq!(foo.bar.baz, true); + + let gctx: GlobalContext = GlobalContextBuilder::new() + .config_arg("foo.bar.baz=true") + .build(); + assert_error( + gctx.get::("foo").unwrap_err(), + "\ +error in --config cli option: could not load config key `foo.bar` + +Caused by: + missing field `bax`", + ); +} + +#[cargo_test] +fn git_features() { + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GIT", "shallow-index") + .build(); + assert!(do_check( + gctx, + Some(GitFeatures { + shallow_index: true, + ..GitFeatures::default() + }), + )); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GIT", "shallow-index,abc") + .build(); + assert_error( + gctx.get::>("unstable") + .unwrap_err(), + "\ +error in environment variable `CARGO_UNSTABLE_GIT`: could not load config key `unstable.git` + +Caused by: +[..]unstable 'git' only takes [..] as valid inputs", + ); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GIT", "shallow-deps") + .build(); + assert!(do_check( + gctx, + Some(GitFeatures { + shallow_index: false, + shallow_deps: true, + }), + )); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GIT", "true") + .build(); + assert!(do_check(gctx, Some(GitFeatures::all()))); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GIT_SHALLOW_INDEX", "true") + .build(); + assert!(do_check( + gctx, + Some(GitFeatures { + shallow_index: true, + ..Default::default() + }), + )); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GIT_SHALLOW_INDEX", "true") + .env("CARGO_UNSTABLE_GIT_SHALLOW_DEPS", "true") + .build(); + assert!(do_check( + gctx, + Some(GitFeatures { + shallow_index: true, + shallow_deps: true, + ..Default::default() + }), + )); + + write_config_toml( + "\ +[unstable] +git = 'shallow-index' +", + ); + let gctx = GlobalContextBuilder::new().build(); + assert!(do_check( + gctx, + Some(GitFeatures { + shallow_index: true, + shallow_deps: false, + }), + )); + + write_config_toml( + "\ + [unstable.git] + shallow_deps = false + shallow_index = true + ", + ); + let gctx = GlobalContextBuilder::new().build(); + assert!(do_check( + gctx, + Some(GitFeatures { + shallow_index: true, + shallow_deps: false, + ..Default::default() + }), + )); + + write_config_toml( + "\ + [unstable.git] + ", + ); + let gctx = GlobalContextBuilder::new().build(); + assert!(do_check(gctx, Some(Default::default()))); + + fn do_check(gctx: GlobalContext, expect: Option) -> bool { + let unstable_flags = gctx + .get::>("unstable") + .unwrap() + .unwrap(); + unstable_flags.git == expect + } +} + +#[cargo_test] +fn gitoxide_features() { + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GITOXIDE", "fetch") + .build(); + assert!(do_check( + gctx, + Some(GitoxideFeatures { + fetch: true, + ..GitoxideFeatures::default() + }), + )); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GITOXIDE", "fetch,abc") + .build(); + + assert_error( + gctx.get::>("unstable") + .unwrap_err(), + "\ +error in environment variable `CARGO_UNSTABLE_GITOXIDE`: could not load config key `unstable.gitoxide` + +Caused by: +[..]unstable 'gitoxide' only takes [..] as valid inputs, for shallow fetches see `-Zgit=shallow-index,shallow-deps`", +); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GITOXIDE", "true") + .build(); + assert!(do_check(gctx, Some(GitoxideFeatures::all()))); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_GITOXIDE_FETCH", "true") + .build(); + assert!(do_check( + gctx, + Some(GitoxideFeatures { + fetch: true, + ..Default::default() + }), + )); + + write_config_toml( + "\ +[unstable] +gitoxide = \"fetch\" +", + ); + let gctx = GlobalContextBuilder::new().build(); + assert!(do_check( + gctx, + Some(GitoxideFeatures { + fetch: true, + ..GitoxideFeatures::default() + }), + )); + + write_config_toml( + "\ + [unstable.gitoxide] + fetch = true + checkout = false + internal_use_git2 = false + ", + ); + let gctx = GlobalContextBuilder::new().build(); + assert!(do_check( + gctx, + Some(GitoxideFeatures { + fetch: true, + checkout: false, + internal_use_git2: false, + }), + )); + + write_config_toml( + "\ + [unstable.gitoxide] + ", + ); + let gctx = GlobalContextBuilder::new().build(); + assert!(do_check(gctx, Some(Default::default()))); + + fn do_check(gctx: GlobalContext, expect: Option) -> bool { + let unstable_flags = gctx + .get::>("unstable") + .unwrap() + .unwrap(); + unstable_flags.gitoxide == expect + } +} + +#[cargo_test] +fn nonmergable_lists() { + let root_path = paths::root().join(".cargo/config.toml"); + write_config_at( + &root_path, + "\ +[registries.example] +credential-provider = ['a', 'b'] +", + ); + + let foo_path = paths::root().join("foo/.cargo/config.toml"); + write_config_at( + &foo_path, + "\ +[registries.example] +credential-provider = ['c', 'd'] +", + ); + + let gctx = GlobalContextBuilder::new().cwd("foo").build(); + let provider = gctx + .get::>(&format!("registries.example")) + .unwrap() + .unwrap() + .credential_provider + .unwrap(); + assert_eq!(provider.path.raw_value(), "c"); + assert_eq!(provider.args, ["d"]); +} + +#[cargo_test] +fn build_std() { + let gctx = GlobalContextBuilder::new() + .env("CARGO_UNSTABLE_BUILD_STD", "core,std,panic_abort") + .build(); + let value = gctx + .get::>("unstable") + .unwrap() + .unwrap() + .build_std + .unwrap(); + assert_eq!( + value, + vec![ + "core".to_string(), + "std".to_string(), + "panic_abort".to_string(), + ], + ); + + let gctx = GlobalContextBuilder::new() + .config_arg("unstable.build-std=['core', 'std,panic_abort']") + .build(); + let value = gctx + .get::>("unstable") + .unwrap() + .unwrap() + .build_std + .unwrap(); + assert_eq!( + value, + vec![ + "core".to_string(), + "std".to_string(), + "panic_abort".to_string(), + ] + ); + + let gctx = GlobalContextBuilder::new() + .env( + "CARGO_UNSTABLE_BUILD_STD_FEATURES", + "backtrace,panic-unwind,windows_raw_dylib", + ) + .build(); + let value = gctx + .get::>("unstable") + .unwrap() + .unwrap() + .build_std_features + .unwrap(); + assert_eq!( + value, + vec![ + "backtrace".to_string(), + "panic-unwind".to_string(), + "windows_raw_dylib".to_string(), + ] + ); + + let gctx = GlobalContextBuilder::new() + .config_arg("unstable.build-std-features=['backtrace', 'panic-unwind,windows_raw_dylib']") + .build(); + let value = gctx + .get::>("unstable") + .unwrap() + .unwrap() + .build_std_features + .unwrap(); + assert_eq!( + value, + vec![ + "backtrace".to_string(), + "panic-unwind".to_string(), + "windows_raw_dylib".to_string(), + ] + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_cli.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_cli.rs new file mode 100644 index 000000000..c9eed19fd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_cli.rs @@ -0,0 +1,577 @@ +//! Tests for the --config CLI option. + +use std::{collections::HashMap, fs}; + +use cargo::util::context::Definition; +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +use super::config::{ + assert_error, read_output, write_config_at, write_config_toml, GlobalContextBuilder, +}; + +#[cargo_test] +fn basic() { + // Simple example. + let gctx = GlobalContextBuilder::new() + .config_arg("foo='bar'") + .config_arg("net.git-fetch-with-cli=true") + .build(); + assert_eq!(gctx.get::("foo").unwrap(), "bar"); + assert_eq!(gctx.net_config().unwrap().git_fetch_with_cli, Some(true)); +} + +#[cargo_test] +fn cli_priority() { + // Command line takes priority over files and env vars. + write_config_toml( + " + demo_list = ['a'] + [build] + jobs = 3 + rustc = 'file' + [term] + quiet = false + verbose = false + ", + ); + let gctx = GlobalContextBuilder::new().build(); + assert_eq!(gctx.get::("build.jobs").unwrap(), 3); + assert_eq!(gctx.get::("build.rustc").unwrap(), "file"); + assert_eq!(gctx.get::("term.quiet").unwrap(), false); + assert_eq!(gctx.get::("term.verbose").unwrap(), false); + + let gctx = GlobalContextBuilder::new() + .env("CARGO_BUILD_JOBS", "2") + .env("CARGO_BUILD_RUSTC", "env") + .env("CARGO_TERM_VERBOSE", "false") + .env("CARGO_NET_GIT_FETCH_WITH_CLI", "false") + .config_arg("build.jobs=1") + .config_arg("build.rustc='cli'") + .config_arg("term.verbose=true") + .config_arg("net.git-fetch-with-cli=true") + .build(); + assert_eq!(gctx.get::("build.jobs").unwrap(), 1); + assert_eq!(gctx.get::("build.rustc").unwrap(), "cli"); + assert_eq!(gctx.get::("term.verbose").unwrap(), true); + assert_eq!(gctx.net_config().unwrap().git_fetch_with_cli, Some(true)); + + // Setting both term.verbose and term.quiet is invalid and is tested + // in the run test suite. + let gctx = GlobalContextBuilder::new() + .env("CARGO_TERM_QUIET", "false") + .config_arg("term.quiet=true") + .build(); + assert_eq!(gctx.get::("term.quiet").unwrap(), true); +} + +#[cargo_test] +fn merge_primitives_for_multiple_cli_occurrences() { + let config_path0 = ".cargo/file0.toml"; + write_config_at(config_path0, "k = 'file0'"); + let config_path1 = ".cargo/file1.toml"; + write_config_at(config_path1, "k = 'file1'"); + + // k=env0 + let gctx = GlobalContextBuilder::new().env("CARGO_K", "env0").build(); + assert_eq!(gctx.get::("k").unwrap(), "env0"); + + // k=env0 + // --config k='cli0' + // --config k='cli1' + let gctx = GlobalContextBuilder::new() + .env("CARGO_K", "env0") + .config_arg("k='cli0'") + .config_arg("k='cli1'") + .build(); + assert_eq!(gctx.get::("k").unwrap(), "cli1"); + + // Env has a lower priority when comparing with file from CLI arg. + // + // k=env0 + // --config k='cli0' + // --config k='cli1' + // --config .cargo/file0.toml + let gctx = GlobalContextBuilder::new() + .env("CARGO_K", "env0") + .config_arg("k='cli0'") + .config_arg("k='cli1'") + .config_arg(config_path0) + .build(); + assert_eq!(gctx.get::("k").unwrap(), "file0"); + + // k=env0 + // --config k='cli0' + // --config k='cli1' + // --config .cargo/file0.toml + // --config k='cli2' + let gctx = GlobalContextBuilder::new() + .env("CARGO_K", "env0") + .config_arg("k='cli0'") + .config_arg("k='cli1'") + .config_arg(config_path0) + .config_arg("k='cli2'") + .build(); + assert_eq!(gctx.get::("k").unwrap(), "cli2"); + + // k=env0 + // --config k='cli0' + // --config k='cli1' + // --config .cargo/file0.toml + // --config k='cli2' + // --config .cargo/file1.toml + let gctx = GlobalContextBuilder::new() + .env("CARGO_K", "env0") + .config_arg("k='cli0'") + .config_arg("k='cli1'") + .config_arg(config_path0) + .config_arg("k='cli2'") + .config_arg(config_path1) + .build(); + assert_eq!(gctx.get::("k").unwrap(), "file1"); +} + +#[cargo_test] +fn merges_array() { + // Array entries are appended. + write_config_toml( + " + [build] + rustflags = ['--file'] + ", + ); + let gctx = GlobalContextBuilder::new() + .config_arg("build.rustflags = ['--cli']") + .build(); + assert_eq!( + gctx.get::>("build.rustflags").unwrap(), + ["--file", "--cli"] + ); + + // With normal env. + let gctx = GlobalContextBuilder::new() + .env("CARGO_BUILD_RUSTFLAGS", "--env1 --env2") + .config_arg("build.rustflags = ['--cli']") + .build(); + assert_eq!( + gctx.get::>("build.rustflags").unwrap(), + ["--file", "--env1", "--env2", "--cli"] + ); + + // With advanced-env. + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_BUILD_RUSTFLAGS", "--env") + .config_arg("build.rustflags = ['--cli']") + .build(); + assert_eq!( + gctx.get::>("build.rustflags").unwrap(), + ["--file", "--env", "--cli"] + ); + + // Merges multiple instances. + let gctx = GlobalContextBuilder::new() + .config_arg("build.rustflags=['--one']") + .config_arg("build.rustflags=['--two']") + .build(); + assert_eq!( + gctx.get::>("build.rustflags").unwrap(), + ["--file", "--one", "--two"] + ); +} + +#[cargo_test] +fn string_list_array() { + // Using the StringList type. + write_config_toml( + " + [build] + rustflags = ['--file'] + ", + ); + let gctx = GlobalContextBuilder::new() + .config_arg("build.rustflags = ['--cli']") + .build(); + assert_eq!( + gctx.get::("build.rustflags") + .unwrap() + .as_slice(), + ["--file", "--cli"] + ); + + // With normal env. + let gctx = GlobalContextBuilder::new() + .env("CARGO_BUILD_RUSTFLAGS", "--env1 --env2") + .config_arg("build.rustflags = ['--cli']") + .build(); + assert_eq!( + gctx.get::("build.rustflags") + .unwrap() + .as_slice(), + ["--file", "--env1", "--env2", "--cli"] + ); + + // With advanced-env. + let gctx = GlobalContextBuilder::new() + .unstable_flag("advanced-env") + .env("CARGO_BUILD_RUSTFLAGS", "['--env']") + .config_arg("build.rustflags = ['--cli']") + .build(); + assert_eq!( + gctx.get::("build.rustflags") + .unwrap() + .as_slice(), + ["--file", "--env", "--cli"] + ); +} + +#[cargo_test] +fn merges_table() { + // Tables are merged. + write_config_toml( + " + [foo] + key1 = 1 + key2 = 2 + key3 = 3 + ", + ); + let gctx = GlobalContextBuilder::new() + .config_arg("foo.key2 = 4") + .config_arg("foo.key3 = 5") + .config_arg("foo.key4 = 6") + .build(); + assert_eq!(gctx.get::("foo.key1").unwrap(), 1); + assert_eq!(gctx.get::("foo.key2").unwrap(), 4); + assert_eq!(gctx.get::("foo.key3").unwrap(), 5); + assert_eq!(gctx.get::("foo.key4").unwrap(), 6); + + // With env. + let gctx = GlobalContextBuilder::new() + .env("CARGO_FOO_KEY3", "7") + .env("CARGO_FOO_KEY4", "8") + .env("CARGO_FOO_KEY5", "9") + .config_arg("foo.key2 = 4") + .config_arg("foo.key3 = 5") + .config_arg("foo.key4 = 6") + .build(); + assert_eq!(gctx.get::("foo.key1").unwrap(), 1); + assert_eq!(gctx.get::("foo.key2").unwrap(), 4); + assert_eq!(gctx.get::("foo.key3").unwrap(), 5); + assert_eq!(gctx.get::("foo.key4").unwrap(), 6); + assert_eq!(gctx.get::("foo.key5").unwrap(), 9); +} + +#[cargo_test] +fn merge_array_mixed_def_paths() { + // Merging of arrays with different def sites. + write_config_toml( + " + paths = ['file'] + ", + ); + // Create a directory for CWD to differentiate the paths. + let somedir = paths::root().join("somedir"); + fs::create_dir(&somedir).unwrap(); + let gctx = GlobalContextBuilder::new() + .cwd(&somedir) + .config_arg("paths=['cli']") + // env is currently ignored for get_list() + .env("CARGO_PATHS", "env") + .build(); + let paths = gctx.get_list("paths").unwrap().unwrap(); + // The definition for the root value is somewhat arbitrary, but currently starts with the file because that is what is loaded first. + assert_eq!(paths.definition, Definition::Path(paths::root())); + assert_eq!(paths.val.len(), 2); + assert_eq!(paths.val[0].0, "file"); + assert_eq!(paths.val[0].1.root(&gctx), paths::root()); + assert_eq!(paths.val[1].0, "cli"); + assert_eq!(paths.val[1].1.root(&gctx), somedir); +} + +#[cargo_test] +fn enforces_format() { + // These dotted key expressions should all be fine. + let gctx = GlobalContextBuilder::new() + .config_arg("a=true") + .config_arg(" b.a = true ") + .config_arg("c.\"b\".'a'=true") + .config_arg("d.\"=\".'='=true") + .config_arg("e.\"'\".'\"'=true") + .build(); + assert_eq!(gctx.get::("a").unwrap(), true); + assert_eq!( + gctx.get::>("b").unwrap(), + HashMap::from([("a".to_string(), true)]) + ); + assert_eq!( + gctx.get::>>("c") + .unwrap(), + HashMap::from([("b".to_string(), HashMap::from([("a".to_string(), true)]))]) + ); + assert_eq!( + gctx.get::>>("d") + .unwrap(), + HashMap::from([("=".to_string(), HashMap::from([("=".to_string(), true)]))]) + ); + assert_eq!( + gctx.get::>>("e") + .unwrap(), + HashMap::from([("'".to_string(), HashMap::from([("\"".to_string(), true)]))]) + ); + + // But anything that's not a dotted key expression should be disallowed. + let _ = GlobalContextBuilder::new() + .config_arg("[a] foo=true") + .build_err() + .unwrap_err(); + let _ = GlobalContextBuilder::new() + .config_arg("a = true\nb = true") + .build_err() + .unwrap_err(); + + // We also disallow overwriting with tables since it makes merging unclear. + let _ = GlobalContextBuilder::new() + .config_arg("a = { first = true, second = false }") + .build_err() + .unwrap_err(); + let _ = GlobalContextBuilder::new() + .config_arg("a = { first = true }") + .build_err() + .unwrap_err(); +} + +#[cargo_test] +fn unused_key() { + // Unused key passed on command line. + let gctx = GlobalContextBuilder::new() + .config_arg("build.unused = 2") + .build(); + + gctx.build_config().unwrap(); + let output = read_output(gctx); + let expected = str![[r#" +[WARNING] unused config key `build.unused` in `--config cli option` + +"#]]; + assert_e2e().eq(&output, expected); +} + +#[cargo_test] +fn rerooted_remains() { + // Re-rooting keeps cli args. + let somedir = paths::root().join("somedir"); + fs::create_dir_all(somedir.join(".cargo")).unwrap(); + fs::write( + somedir.join(".cargo").join("config"), + " + a = 'file1' + b = 'file2' + ", + ) + .unwrap(); + let mut gctx = GlobalContextBuilder::new() + .cwd(&somedir) + .config_arg("b='cli1'") + .config_arg("c='cli2'") + .build(); + assert_eq!(gctx.get::("a").unwrap(), "file1"); + assert_eq!(gctx.get::("b").unwrap(), "cli1"); + assert_eq!(gctx.get::("c").unwrap(), "cli2"); + + gctx.reload_rooted_at(paths::root()).unwrap(); + + assert_eq!(gctx.get::>("a").unwrap(), None); + assert_eq!(gctx.get::("b").unwrap(), "cli1"); + assert_eq!(gctx.get::("c").unwrap(), "cli2"); +} + +#[cargo_test] +fn bad_parse() { + // Fail to TOML parse. + let gctx = GlobalContextBuilder::new().config_arg("abc").build_err(); + assert_error( + gctx.unwrap_err(), + "\ +failed to parse value from --config argument `abc` as a dotted key expression + +Caused by: + TOML parse error at line 1, column 4 + | +1 | abc + | ^ +expected `.`, `=` +", + ); + + let gctx = GlobalContextBuilder::new().config_arg("").build_err(); + assert_error( + gctx.unwrap_err(), + "--config argument `` was not a TOML dotted key expression (such as `build.jobs = 2`)", + ); +} + +#[cargo_test] +fn too_many_values() { + // Currently restricted to only 1 value. + let gctx = GlobalContextBuilder::new() + .config_arg("a=1\nb=2") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +--config argument `a=1 +b=2` was not a TOML dotted key expression (such as `build.jobs = 2`)", + ); +} + +#[cargo_test] +fn no_disallowed_values() { + let gctx = GlobalContextBuilder::new() + .config_arg("registry.token=\"hello\"") + .build_err(); + assert_error( + gctx.unwrap_err(), + "registry.token cannot be set through --config for security reasons", + ); + let gctx = GlobalContextBuilder::new() + .config_arg("registries.crates-io.token=\"hello\"") + .build_err(); + assert_error( + gctx.unwrap_err(), + "registries.crates-io.token cannot be set through --config for security reasons", + ); + let gctx = GlobalContextBuilder::new() + .config_arg("registry.secret-key=\"hello\"") + .build_err(); + assert_error( + gctx.unwrap_err(), + "registry.secret-key cannot be set through --config for security reasons", + ); + let gctx = GlobalContextBuilder::new() + .config_arg("registries.crates-io.secret-key=\"hello\"") + .build_err(); + assert_error( + gctx.unwrap_err(), + "registries.crates-io.secret-key cannot be set through --config for security reasons", + ); +} + +#[cargo_test] +fn no_inline_table_value() { + // Disallow inline tables + let gctx = GlobalContextBuilder::new() + .config_arg("a.b={c = \"d\"}") + .build_err(); + assert_error( + gctx.unwrap_err(), + "--config argument `a.b={c = \"d\"}` sets a value to an inline table, which is not accepted", + ); +} + +#[cargo_test] +fn no_array_of_tables_values() { + // Disallow array-of-tables when not in dotted form + let gctx = GlobalContextBuilder::new() + .config_arg("[[a.b]]\nc = \"d\"") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +--config argument `[[a.b]] +c = \"d\"` was not a TOML dotted key expression (such as `build.jobs = 2`)", + ); +} + +#[cargo_test] +fn no_comments() { + // Disallow comments in dotted form. + let gctx = GlobalContextBuilder::new() + .config_arg("a.b = \"c\" # exactly") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +--config argument `a.b = \"c\" # exactly` includes non-whitespace decoration", + ); + + let gctx = GlobalContextBuilder::new() + .config_arg("# exactly\na.b = \"c\"") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +--config argument `# exactly\na.b = \"c\"` includes non-whitespace decoration", + ); +} + +#[cargo_test] +fn bad_cv_convert() { + // ConfigValue does not support all TOML types. + let gctx = GlobalContextBuilder::new() + .config_arg("a=2019-12-01") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +failed to convert --config argument `a=2019-12-01` + +Caused by: + failed to parse key `a` + +Caused by: + found TOML configuration value of unknown type `datetime`", + ); +} + +#[cargo_test] +fn fail_to_merge_multiple_args() { + // Error message when multiple args fail to merge. + let gctx = GlobalContextBuilder::new() + .config_arg("foo='a'") + .config_arg("foo=['a']") + .build_err(); + // This is a little repetitive, but hopefully the user can figure it out. + assert_error( + gctx.unwrap_err(), + "\ +failed to merge --config argument `foo=['a']` + +Caused by: + failed to merge key `foo` between --config cli option and --config cli option + +Caused by: + failed to merge config value from `--config cli option` into `--config cli option`: \ + expected string, but found array", + ); +} + +#[cargo_test] +fn cli_path() { + // --config path_to_file + fs::write(paths::root().join("myconfig.toml"), "key = 123").unwrap(); + let gctx = GlobalContextBuilder::new() + .cwd(paths::root()) + .config_arg("myconfig.toml") + .build(); + assert_eq!(gctx.get::("key").unwrap(), 123); + + let gctx = GlobalContextBuilder::new() + .config_arg("missing.toml") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +failed to parse value from --config argument `missing.toml` as a dotted key expression + +Caused by: + TOML parse error at line 1, column 13 + | +1 | missing.toml + | ^ +expected `.`, `=` +", + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_include.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_include.rs new file mode 100644 index 000000000..468115dd5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/config_include.rs @@ -0,0 +1,495 @@ +//! Tests for `include` config field. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +use super::config::{assert_error, write_config_at, write_config_toml, GlobalContextBuilder}; + +#[cargo_test] +fn gated() { + // Requires -Z flag. + write_config_toml("include='other.toml'"); + write_config_at( + ".cargo/other.toml", + " + othervalue = 1 + ", + ); + let gctx = GlobalContextBuilder::new().build(); + assert_eq!(gctx.get::>("othervalue").unwrap(), None); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .build(); + assert_eq!(gctx.get::("othervalue").unwrap(), 1); +} + +#[cargo_test] +fn simple() { + // Simple test. + write_config_at( + ".cargo/config.toml", + " + include = 'other.toml' + key1 = 1 + key2 = 2 + ", + ); + write_config_at( + ".cargo/other.toml", + " + key2 = 3 + key3 = 4 + ", + ); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .build(); + assert_eq!(gctx.get::("key1").unwrap(), 1); + assert_eq!(gctx.get::("key2").unwrap(), 2); + assert_eq!(gctx.get::("key3").unwrap(), 4); +} + +#[cargo_test] +fn enable_in_unstable_config() { + // config-include enabled in the unstable config table: + write_config_at( + ".cargo/config.toml", + " + include = 'other.toml' + key1 = 1 + key2 = 2 + + [unstable] + config-include = true + ", + ); + write_config_at( + ".cargo/other.toml", + " + key2 = 3 + key3 = 4 + ", + ); + let gctx = GlobalContextBuilder::new() + .nightly_features_allowed(true) + .build(); + assert_eq!(gctx.get::("key1").unwrap(), 1); + assert_eq!(gctx.get::("key2").unwrap(), 2); + assert_eq!(gctx.get::("key3").unwrap(), 4); +} + +#[cargo_test] +fn mix_of_hierarchy_and_include() { + write_config_at( + "foo/.cargo/config.toml", + " + include = 'other.toml' + key1 = 1 + + # also make sure unstable flags merge in the correct order + [unstable] + features = ['1'] + ", + ); + write_config_at( + "foo/.cargo/other.toml", + " + key1 = 2 + key2 = 2 + + [unstable] + features = ['2'] + ", + ); + write_config_at( + ".cargo/config.toml", + " + include = 'other.toml' + key1 = 3 + key2 = 3 + key3 = 3 + + [unstable] + features = ['3'] + ", + ); + write_config_at( + ".cargo/other.toml", + " + key1 = 4 + key2 = 4 + key3 = 4 + key4 = 4 + + [unstable] + features = ['4'] + ", + ); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .cwd("foo") + .nightly_features_allowed(true) + .build(); + assert_eq!(gctx.get::("key1").unwrap(), 1); + assert_eq!(gctx.get::("key2").unwrap(), 2); + assert_eq!(gctx.get::("key3").unwrap(), 3); + assert_eq!(gctx.get::("key4").unwrap(), 4); + assert_eq!( + gctx.get::>("unstable.features").unwrap(), + vec![ + "4".to_string(), + "3".to_string(), + "2".to_string(), + "1".to_string() + ] + ); +} + +#[cargo_test] +fn mix_of_hierarchy_and_include_with_enable_in_unstable_config() { + // `mix_of_hierarchy_and_include`, but with the config-include + // feature itself enabled in the unstable config table: + write_config_at( + "foo/.cargo/config.toml", + " + include = 'other.toml' + key1 = 1 + + # also make sure unstable flags merge in the correct order + [unstable] + features = ['1'] + config-include = true + ", + ); + write_config_at( + "foo/.cargo/other.toml", + " + key1 = 2 + key2 = 2 + + [unstable] + features = ['2'] + ", + ); + write_config_at( + ".cargo/config.toml", + " + include = 'other.toml' + key1 = 3 + key2 = 3 + key3 = 3 + + [unstable] + features = ['3'] + ", + ); + write_config_at( + ".cargo/other.toml", + " + key1 = 4 + key2 = 4 + key3 = 4 + key4 = 4 + + [unstable] + features = ['4'] + ", + ); + let gctx = GlobalContextBuilder::new() + .cwd("foo") + .nightly_features_allowed(true) + .build(); + assert_eq!(gctx.get::("key1").unwrap(), 1); + assert_eq!(gctx.get::("key2").unwrap(), 2); + assert_eq!(gctx.get::("key3").unwrap(), 3); + assert_eq!(gctx.get::("key4").unwrap(), 4); + assert_eq!( + gctx.get::>("unstable.features").unwrap(), + vec![ + "4".to_string(), + "3".to_string(), + "2".to_string(), + "1".to_string() + ] + ); +} + +#[cargo_test] +fn works_with_cli() { + write_config_at( + ".cargo/config.toml", + " + include = 'other.toml' + [build] + rustflags = ['-W', 'unused'] + ", + ); + write_config_at( + ".cargo/other.toml", + " + [build] + rustflags = ['-W', 'unsafe-code'] + ", + ); + let p = project().file("src/lib.rs", "").build(); + p.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-W unused` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -v -Z config-include") + .masquerade_as_nightly_cargo(&["config-include"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-W unsafe-code -W unused` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn left_to_right_bottom_to_top() { + // How it merges multiple nested includes. + write_config_at( + ".cargo/config.toml", + " + include = ['left-middle.toml', 'right-middle.toml'] + top = 1 + ", + ); + write_config_at( + ".cargo/right-middle.toml", + " + include = 'right-bottom.toml' + top = 0 + right-middle = 0 + ", + ); + write_config_at( + ".cargo/right-bottom.toml", + " + top = -1 + right-middle = -1 + right-bottom = -1 + ", + ); + write_config_at( + ".cargo/left-middle.toml", + " + include = 'left-bottom.toml' + top = -2 + right-middle = -2 + right-bottom = -2 + left-middle = -2 + ", + ); + write_config_at( + ".cargo/left-bottom.toml", + " + top = -3 + right-middle = -3 + right-bottom = -3 + left-middle = -3 + left-bottom = -3 + ", + ); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .build(); + assert_eq!(gctx.get::("top").unwrap(), 1); + assert_eq!(gctx.get::("right-middle").unwrap(), 0); + assert_eq!(gctx.get::("right-bottom").unwrap(), -1); + assert_eq!(gctx.get::("left-middle").unwrap(), -2); + assert_eq!(gctx.get::("left-bottom").unwrap(), -3); +} + +#[cargo_test] +fn missing_file() { + // Error when there's a missing file. + write_config_toml("include='missing.toml'"); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .build_err(); + assert_error( + gctx.unwrap_err(), + &format!( + "\ +could not load Cargo configuration + +Caused by: + failed to load config include `missing.toml` from `[..]/.cargo/config.toml` + +Caused by: + failed to read configuration file `[..]/.cargo/missing.toml` + +Caused by: + [NOT_FOUND]", + ), + ); +} + +#[cargo_test] +fn wrong_file_extension() { + // Error when it doesn't end with `.toml`. + write_config_toml("include='config.png'"); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +could not load Cargo configuration + +Caused by: + expected a config include path ending with `.toml`, but found `config.png` from `[ROOT]/.cargo/config.toml`", + ); +} + +#[cargo_test] +fn cycle() { + // Detects a cycle. + write_config_at(".cargo/config.toml", "include='one.toml'"); + write_config_at(".cargo/one.toml", "include='two.toml'"); + write_config_at(".cargo/two.toml", "include='config.toml'"); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +could not load Cargo configuration + +Caused by: + failed to load config include `one.toml` from `[..]/.cargo/config.toml` + +Caused by: + failed to load config include `two.toml` from `[..]/.cargo/one.toml` + +Caused by: + failed to load config include `config.toml` from `[..]/.cargo/two.toml` + +Caused by: + config `include` cycle detected with path `[..]/.cargo/config.toml`", + ); +} + +#[cargo_test] +fn cli_include() { + // Using --config with include. + // CLI takes priority over files. + write_config_at( + ".cargo/config.toml", + " + foo = 1 + bar = 2 + ", + ); + write_config_at(".cargo/config-foo.toml", "foo = 2"); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .config_arg("include='.cargo/config-foo.toml'") + .build(); + assert_eq!(gctx.get::("foo").unwrap(), 2); + assert_eq!(gctx.get::("bar").unwrap(), 2); +} + +#[cargo_test] +fn bad_format() { + // Not a valid format. + write_config_toml("include = 1"); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .build_err(); + assert_error( + gctx.unwrap_err(), + "\ +could not load Cargo configuration + +Caused by: + `include` expected a string or list, but found integer in `[..]/.cargo/config.toml`", + ); +} + +#[cargo_test] +fn cli_include_failed() { + // Error message when CLI include fails to load. + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .config_arg("include='foobar.toml'") + .build_err(); + assert_error( + gctx.unwrap_err(), + &format!( + "\ +failed to load --config include + +Caused by: + failed to load config include `foobar.toml` from `--config cli option` + +Caused by: + failed to read configuration file `[..]/foobar.toml` + +Caused by: + [NOT_FOUND]" + ), + ); +} + +#[cargo_test] +fn cli_merge_failed() { + // Error message when CLI include merge fails. + write_config_toml("foo = ['a']"); + write_config_at( + ".cargo/other.toml", + " + foo = 'b' + ", + ); + let gctx = GlobalContextBuilder::new() + .unstable_flag("config-include") + .config_arg("include='.cargo/other.toml'") + .build_err(); + // Maybe this error message should mention it was from an include file? + assert_error( + gctx.unwrap_err(), + "\ +failed to merge --config key `foo` into `[..]/.cargo/config.toml` + +Caused by: + failed to merge config value from `[..]/.cargo/other.toml` into `[..]/.cargo/config.toml`: \ + expected array, but found string", + ); +} + +#[cargo_test] +fn cli_include_take_priority_over_env() { + write_config_at(".cargo/include.toml", "k='include'"); + + // k=env + let gctx = GlobalContextBuilder::new().env("CARGO_K", "env").build(); + assert_eq!(gctx.get::("k").unwrap(), "env"); + + // k=env + // --config 'include=".cargo/include.toml"' + let gctx = GlobalContextBuilder::new() + .env("CARGO_K", "env") + .unstable_flag("config-include") + .config_arg("include='.cargo/include.toml'") + .build(); + assert_eq!(gctx.get::("k").unwrap(), "include"); + + // k=env + // --config '.cargo/foo.toml' + write_config_at(".cargo/foo.toml", "include='include.toml'"); + let gctx = GlobalContextBuilder::new() + .env("CARGO_K", "env") + .unstable_flag("config-include") + .config_arg(".cargo/foo.toml") + .build(); + assert_eq!(gctx.get::("k").unwrap(), "include"); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/corrupt_git.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/corrupt_git.rs new file mode 100644 index 000000000..ee4c720fb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/corrupt_git.rs @@ -0,0 +1,161 @@ +//! Tests for corrupt git repos. + +use std::fs; +use std::path::{Path, PathBuf}; + +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, git, project}; +use cargo_util::paths as cargopaths; + +#[cargo_test] +fn deleting_database_files() { + let project = project(); + let git_project = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + }); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + authors = [] + + [dependencies] + bar = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + project.cargo("check").run(); + + let mut files = Vec::new(); + find_files(&paths::home().join(".cargo/git/db"), &mut files); + assert!(!files.is_empty()); + + let log = "cargo::sources::git=trace"; + for file in files { + if !file.exists() { + continue; + } + println!("deleting {}", file.display()); + cargopaths::remove_file(&file).unwrap(); + project.cargo("check -v").env("CARGO_LOG", log).run(); + + if !file.exists() { + continue; + } + println!("truncating {}", file.display()); + make_writable(&file); + fs::OpenOptions::new() + .write(true) + .open(&file) + .unwrap() + .set_len(2) + .unwrap(); + project.cargo("check -v").env("CARGO_LOG", log).run(); + } +} + +#[cargo_test] +fn deleting_checkout_files() { + let project = project(); + let git_project = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + }); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + authors = [] + + [dependencies] + bar = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + project.cargo("check").run(); + + let dir = paths::home() + .join(".cargo/git/checkouts") + // get the first entry in the checkouts dir for the package's location + .read_dir() + .unwrap() + .next() + .unwrap() + .unwrap() + .path() + // get the first child of that checkout dir for our checkout + .read_dir() + .unwrap() + .next() + .unwrap() + .unwrap() + .path() + // and throw on .git to corrupt things + .join(".git"); + let mut files = Vec::new(); + find_files(&dir, &mut files); + assert!(!files.is_empty()); + + let log = "cargo::sources::git=trace"; + for file in files { + if !file.exists() { + continue; + } + println!("deleting {}", file.display()); + cargopaths::remove_file(&file).unwrap(); + project.cargo("check -v").env("CARGO_LOG", log).run(); + + if !file.exists() { + continue; + } + println!("truncating {}", file.display()); + make_writable(&file); + fs::OpenOptions::new() + .write(true) + .open(&file) + .unwrap() + .set_len(2) + .unwrap(); + project.cargo("check -v").env("CARGO_LOG", log).run(); + } +} + +fn make_writable(path: &Path) { + let mut p = path.metadata().unwrap().permissions(); + p.set_readonly(false); + fs::set_permissions(path, p).unwrap(); +} + +fn find_files(path: &Path, dst: &mut Vec) { + for e in path.read_dir().unwrap() { + let e = e.unwrap(); + let path = e.path(); + if e.file_type().unwrap().is_dir() { + find_files(&path, dst); + } else { + dst.push(path); + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/credential_process.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/credential_process.rs new file mode 100644 index 000000000..5ebabfad6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/credential_process.rs @@ -0,0 +1,769 @@ +//! Tests for credential-process. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Package, TestRegistry}; +use cargo_test_support::{basic_manifest, cargo_process, paths, project, registry, str, Project}; + +fn toml_bin(proj: &Project, name: &str) -> String { + proj.bin(name).display().to_string().replace('\\', "\\\\") +} + +/// Setup for a test that will issue a command that needs to fetch a token. +/// +/// This does the following: +/// +/// * Spawn a thread that will act as an API server. +/// * Create a simple credential-process that will generate a fake token. +/// * Create a simple `foo` project to run the test against. +/// * Configure the credential-process config. +/// +/// Returns the simple `foo` project to test against and the API server handle. +fn get_token_test() -> (Project, TestRegistry) { + // API server that checks that the token is included correctly. + let server = registry::RegistryBuilder::new() + .no_configure_token() + .token(cargo_test_support::registry::Token::Plaintext( + "sekrit".to_string(), + )) + .alternative() + .http_api() + .http_index() + .auth_required() + .build(); + + let provider = build_provider( + "test-cred", + r#"{"Ok":{"kind":"get","token":"sekrit","cache":"session","operation_independent":false}}"#, + ); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [registries.alternative] + index = "{}" + credential-provider = ["{provider}"] + "#, + server.index_url(), + ), + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "MIT" + homepage = "https://example.com/" + "#, + ) + .file("src/lib.rs", "") + .build(); + (p, server) +} + +#[cargo_test] +fn publish() { + // Checks that credential-process is used for `cargo publish`. + let (p, _t) = get_token_test(); + + p.cargo("publish --no-verify --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +{"v":1,"registry":{"index-url":"[..]","name":"alternative","headers":[..]},"kind":"get","operation":"read"} +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]"} +[UPLOADED] foo v0.1.0 to registry `alternative` +[NOTE] waiting for `foo v0.1.0` to be available at registry `alternative`. +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 at registry `alternative` + +"#]]) + .run(); +} + +#[cargo_test] +fn credential_provider_auth_failure() { + let _reg = registry::RegistryBuilder::new() + .http_index() + .auth_required() + .alternative() + .no_configure_token() + .credential_provider(&["cargo:token-from-stdout", "true"]) + .build(); + + cargo_process("install libc --registry=alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] token rejected for `alternative` +You may need to log in using this registry's credential provider + +Caused by: + failed to get successful HTTP response from [..] + body: + [..] +"#]]) + .run(); +} + +#[cargo_test] +fn basic_unsupported() { + // Non-action commands don't support login/logout. + let registry = registry::RegistryBuilder::new() + .no_configure_token() + .credential_provider(&["cargo:token-from-stdout", "false"]) + .build(); + + cargo_process("login") + .with_stdin("abcdefg") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] credential provider `cargo:token-from-stdout false` failed action `login` + +Caused by: + requested operation not supported + +"#]]) + .run(); + + cargo_process("logout") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] credential provider `cargo:token-from-stdout false` failed action `logout` + +Caused by: + requested operation not supported + +"#]]) + .run(); +} + +#[cargo_test] +fn login() { + let registry = registry::RegistryBuilder::new() + .no_configure_token() + .credential_provider(&[ + &build_provider("test-cred", r#"{"Ok": {"kind": "login"}}"#), + "cfg1", + "--cfg2", + ]) + .build(); + + cargo_process("login -- cmd3 --cmd4") + .with_stdin("abcdefg") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[ROOTURL]/api/me","args":["cfg1","--cfg2","cmd3","--cmd4"]} + +"#]]) + .run(); +} + +#[cargo_test] +fn logout() { + let server = registry::RegistryBuilder::new() + .no_configure_token() + .credential_provider(&[&build_provider( + "test-cred", + r#"{"Ok": {"kind": "logout"}}"#, + )]) + .build(); + + cargo_process("logout") + .replace_crates_io(server.index_url()) + .with_stderr_data(str![[r#" +{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"logout"} + +"#]]) + .run(); +} + +#[cargo_test] +fn yank() { + let (p, _t) = get_token_test(); + + p.cargo("yank --version 0.1.0 --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +{"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 + +"#]]) + .run(); +} + +#[cargo_test] +fn owner() { + let (p, _t) = get_token_test(); + + p.cargo("owner --add username --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +{"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! + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_token_output() { + // Error when credential process does not output the expected format for a token. + let cred_proj = project() + .at("cred_proj") + .file("Cargo.toml", &basic_manifest("test-cred", "1.0.0")) + .file("src/main.rs", r#"fn main() { print!("a\nb\n"); } "#) + .build(); + cred_proj.cargo("build").run(); + let _server = registry::RegistryBuilder::new() + .alternative() + .credential_provider(&[ + "cargo:token-from-stdout", + &toml_bin(&cred_proj, "test-cred"), + ]) + .no_configure_token() + .build(); + + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] credential provider `[..]test-cred[EXE]` failed action `get` + +Caused by: + process `[..]` returned more than one line of output; expected a single token + +"#]]) + .run(); +} + +/// Builds a credential provider that echos the request from cargo to stderr, +/// and prints the `response` to stdout. +fn build_provider(name: &str, response: &str) -> String { + // The credential process to use. + let cred_proj = project() + .at(name) + .file("Cargo.toml", &basic_manifest(name, "1.0.0")) + .file( + "src/main.rs", + &r####" + fn main() { + println!(r#"{{"v":[1]}}"#); + assert_eq!(std::env::args().skip(1).next().unwrap(), "--cargo-plugin"); + let mut buffer = String::new(); + std::io::stdin().read_line(&mut buffer).unwrap(); + eprint!("{}", buffer); + use std::io::Write; + std::io::stdout().write_all(r###"[RESPONSE]"###.as_bytes()).unwrap(); + println!(); + } "#### + .replace("[RESPONSE]", response), + ) + .build(); + cred_proj.cargo("build").run(); + toml_bin(&cred_proj, name) +} + +#[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_data(str![[r#" +[UPDATING] crates.io index +[CREDENTIAL] [..]not_found[..] get crates-io +{"v":1[..] +[ERROR] no token found, please run `cargo login` + +"#]]) + .run(); +} + +#[cargo_test] +fn all_not_found() { + let server = registry::RegistryBuilder::new() + .no_configure_token() + .auth_required() + .http_index() + .build(); + let not_found = build_provider("not_found", r#"{"Err": {"kind": "not-found"}}"#); + cargo_util::paths::append( + &paths::home().join(".cargo/config.toml"), + format!( + r#" + [registry] + global-credential-providers = ["not_found"] + [credential-alias] + not_found = ["{not_found}"] + "#, + ) + .as_bytes(), + ) + .unwrap(); + + // 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_data(str![[r#" +[UPDATING] crates.io index +[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"} +[ERROR] no token found, please run `cargo login` + +"#]]) + .run(); +} + +#[cargo_test] +fn all_not_supported() { + let server = registry::RegistryBuilder::new() + .no_configure_token() + .auth_required() + .http_index() + .build(); + let not_supported = + build_provider("not_supported", r#"{"Err": {"kind": "url-not-supported"}}"#); + cargo_util::paths::append( + &paths::home().join(".cargo/config.toml"), + format!( + r#" + [registry] + global-credential-providers = ["not_supported"] + [credential-alias] + not_supported = ["{not_supported}"] + "#, + ) + .as_bytes(), + ) + .unwrap(); + + cargo_process("install -v foo") + .replace_crates_io(server.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[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"} +[ERROR] no credential providers could handle the request + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_providers() { + let server = registry::RegistryBuilder::new() + .no_configure_token() + .build(); + + // Set up two credential providers: the first will fail with "UrlNotSupported" + // and Cargo should skip it. The second should succeed. + let url_not_supported = build_provider( + "url_not_supported", + r#"{"Err": {"kind": "url-not-supported"}}"#, + ); + + let success_provider = build_provider("success_provider", r#"{"Ok": {"kind": "login"}}"#); + + cargo_util::paths::append( + &paths::home().join(".cargo/config.toml"), + format!( + r#" + [registry] + global-credential-providers = ["success_provider", "url_not_supported"] + + [credential-alias] + success_provider = ["{success_provider}"] + url_not_supported = ["{url_not_supported}"] + "#, + ) + .as_bytes(), + ) + .unwrap(); + + cargo_process("login -v") + .with_stdin("abcdefg") + .replace_crates_io(server.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[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":"[ROOTURL]/api/me"} +[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":"[ROOTURL]/api/me"} + +"#]]) + .run(); +} + +#[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_data(str![[r#" +[UPDATING] crates.io index +[WARNING] registry `crates-io` has a token configured in [ROOT]/home/.cargo/credentials.toml 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.toml"), + format!( + r#" + [registry] + global-credential-providers = ["should-not-be-called"] + "#, + ) + .as_bytes(), + ) + .unwrap(); + + cargo_process("login -v") + .with_stdin("abcdefg") + .env("CARGO_REGISTRY_CREDENTIAL_PROVIDER", "cargo:token") + .replace_crates_io(server.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[CREDENTIAL] cargo:token login crates-io +[LOGIN] token for `crates-io` saved + +"#]]) + .run(); + let credentials = + std::fs::read_to_string(paths::home().join(".cargo/credentials.toml")).unwrap(); + assert_eq!(credentials, "[registry]\ntoken = \"abcdefg\"\n"); +} + +#[cargo_test] +fn both_asymmetric_and_token() { + let server = registry::RegistryBuilder::new().build(); + cargo_util::paths::append( + &paths::home().join(".cargo/config.toml"), + format!( + r#" + [registry] + token = "foo" + secret-key = "bar" + "#, + ) + .as_bytes(), + ) + .unwrap(); + + cargo_process("login -Zasymmetric-token -v").with_stdin("abcdefg") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .replace_crates_io(server.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] registry `crates-io` has a `secret_key` configured in [..]config.toml that will be ignored because a `token` is also configured, and the `cargo:token` provider is configured with higher precedence +[CREDENTIAL] cargo:token login crates-io +[LOGIN] token for `crates-io` saved + +"#]]) + .run(); +} + +#[cargo_test] +fn token_caching() { + let server = registry::RegistryBuilder::new() + .no_configure_token() + .no_configure_registry() + .token(cargo_test_support::registry::Token::Plaintext( + "sekrit".to_string(), + )) + .alternative() + .http_api() + .http_index() + .build(); + + // Token should not be re-used if it is expired + let expired_provider = build_provider( + "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( + "non_independent_provider", + r#"{"Ok":{"kind":"get","token":"sekrit","cache":"session","operation_independent":false}}"#, + ); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [registries.alternative] + index = "{}" + credential-provider = ["{expired_provider}"] + "#, + server.index_url(), + ), + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "MIT" + homepage = "https://example.com/" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let output = r#"[UPDATING] `alternative` index +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"read"} +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.0","cksum":"[..]"} +[UPLOADED] foo v0.1.0 to registry `alternative` +[NOTE] waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.0 at registry `alternative` +"#; + + // 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 --registry alternative --no-verify") + .with_stderr_data(output) + .run(); + + let output_non_independent = r#"[UPDATING] `alternative` index +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"read"} +[PACKAGING] foo v0.1.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.1.1 ([ROOT]/foo) +{"v":1,"registry":{"index-url":"[..]","name":"alternative"},"kind":"get","operation":"publish","name":"foo","vers":"0.1.1","cksum":"[..]"} +[UPLOADED] foo v0.1.1 to registry `alternative` +[NOTE] waiting [..] +You may press ctrl-c [..] +[PUBLISHED] foo v0.1.1 at registry `alternative` +"#; + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.1" + edition = "2015" + description = "foo" + license = "MIT" + homepage = "https://example.com/" + "#, + ); + + p.change_file( + ".cargo/config.toml", + &format!( + r#" + [registries.alternative] + index = "{}" + credential-provider = ["{non_independent_provider}"] + "#, + server.index_url(), + ), + ); + + p.cargo("publish --registry alternative --no-verify") + .with_stderr_data(output_non_independent) + .run(); +} + +#[cargo_test] +fn basic_provider() { + let cred_proj = project() + .at("cred_proj") + .file("Cargo.toml", &basic_manifest("test-cred", "1.0.0")) + .file("src/main.rs", r#"fn main() { + eprintln!("CARGO={:?}", std::env::var("CARGO").ok()); + eprintln!("CARGO_REGISTRY_NAME_OPT={:?}", std::env::var("CARGO_REGISTRY_NAME_OPT").ok()); + eprintln!("CARGO_REGISTRY_INDEX_URL={:?}", std::env::var("CARGO_REGISTRY_INDEX_URL").ok()); + print!("sekrit"); + }"#) + .build(); + cred_proj.cargo("build").run(); + + let _server = registry::RegistryBuilder::new() + .no_configure_token() + .credential_provider(&[ + "cargo:token-from-stdout", + &toml_bin(&cred_proj, "test-cred"), + ]) + .token(cargo_test_support::registry::Token::Plaintext( + "sekrit".to_string(), + )) + .alternative() + .http_api() + .auth_required() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + Package::new("bar", "0.0.1").alternative(true).publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +CARGO=Some([..]) +CARGO_REGISTRY_NAME_OPT=Some("alternative") +CARGO_REGISTRY_INDEX_URL=Some("[ROOTURL]/alternative-registry") +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[CHECKING] bar v0.0.1 (registry `alternative`) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .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") + .with_stdin("abcdefg") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[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.toml"), + format!( + r#" + [credential-alias] + "cargo:token" = ["ignored"] + "#, + ) + .as_bytes(), + ) + .unwrap(); + + cargo_process("login") + .with_stdin("abcdefg") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] credential-alias `cargo:token` (defined in `[ROOT]/home/.cargo/config.toml`) will be ignored because it would shadow a built-in credential-provider +[LOGIN] token for `crates-io` saved + +"#]]) + .run(); +} + +#[cargo_test] +fn login_token_from_stdin() { + // Test reading a token from stdin, ensuring newlines are trimmed. + let registry = registry::RegistryBuilder::new() + .no_configure_token() + .credential_provider(&[&build_provider("test-cred", r#"{"Ok": {"kind": "login"}}"#)]) + .build(); + + cargo_process("login") + .replace_crates_io(registry.index_url()) + .with_stdin("abcdefg\n") + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +{"v":1,"registry":{"index-url":"https://github.com/rust-lang/crates.io-index","name":"crates-io"},"kind":"login","token":"abcdefg","login-url":"[ROOTURL]/api/me"} + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_compile.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_compile.rs new file mode 100644 index 000000000..f84efeab1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_compile.rs @@ -0,0 +1,1301 @@ +//! Tests for cross compiling with --target. +//! +//! See `cargo_test_support::cross_compile` for more detail. + +use cargo_test_support::prelude::*; +use cargo_test_support::rustc_host; +use cargo_test_support::str; +use cargo_test_support::{basic_bin_manifest, basic_manifest, cross_compile, project}; + +#[cargo_test] +fn simple_cross() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + &format!( + r#" + fn main() {{ + assert_eq!(std::env::var("TARGET").unwrap(), "{}"); + }} + "#, + cross_compile::alternate() + ), + ) + .file( + "src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let target = cross_compile::alternate(); + p.cargo("build -v --target").arg(&target).run(); + assert!(p.target_bin(target, "foo").is_file()); + + if cross_compile::can_run_on_host() { + p.process(&p.target_bin(target, "foo")).run(); + } +} + +#[cargo_test] +fn simple_cross_config() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [build] + target = "{}" + "#, + cross_compile::alternate() + ), + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + &format!( + r#" + fn main() {{ + assert_eq!(std::env::var("TARGET").unwrap(), "{}"); + }} + "#, + cross_compile::alternate() + ), + ) + .file( + "src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let target = cross_compile::alternate(); + p.cargo("build -v").run(); + assert!(p.target_bin(target, "foo").is_file()); + + if cross_compile::can_run_on_host() { + p.process(&p.target_bin(target, "foo")).run(); + } +} + +#[cargo_test] +fn simple_deps() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::bar(); }") + .build(); + let _p2 = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", "pub fn bar() {}") + .build(); + + let target = cross_compile::alternate(); + p.cargo("build --target").arg(&target).run(); + assert!(p.target_bin(target, "foo").is_file()); + + if cross_compile::can_run_on_host() { + p.process(&p.target_bin(target, "foo")).run(); + } +} + +/// Always take care of setting these so that +/// `cross_compile::alternate()` is the actually-picked target +fn per_crate_target_test( + default_target: Option<&'static str>, + forced_target: Option<&'static str>, + arg_target: Option<&'static str>, +) { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + cargo-features = ["per-package-target"] + + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + {} + {} + "#, + default_target + .map(|t| format!(r#"default-target = "{}""#, t)) + .unwrap_or(String::new()), + forced_target + .map(|t| format!(r#"forced-target = "{}""#, t)) + .unwrap_or(String::new()), + ), + ) + .file( + "build.rs", + &format!( + r#" + fn main() {{ + assert_eq!(std::env::var("TARGET").unwrap(), "{}"); + }} + "#, + cross_compile::alternate() + ), + ) + .file( + "src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let mut cmd = p.cargo("build -v"); + if let Some(t) = arg_target { + cmd.arg("--target").arg(&t); + } + cmd.masquerade_as_nightly_cargo(&["per-package-target"]) + .run(); + assert!(p.target_bin(cross_compile::alternate(), "foo").is_file()); + + if cross_compile::can_run_on_host() { + p.process(&p.target_bin(cross_compile::alternate(), "foo")) + .run(); + } +} + +#[cargo_test] +fn per_crate_default_target_is_default() { + per_crate_target_test(Some(cross_compile::alternate()), None, None); +} + +#[cargo_test] +fn per_crate_default_target_gets_overridden() { + per_crate_target_test( + Some(cross_compile::unused()), + None, + Some(cross_compile::alternate()), + ); +} + +#[cargo_test] +fn per_crate_forced_target_is_default() { + per_crate_target_test(None, Some(cross_compile::alternate()), None); +} + +#[cargo_test] +fn per_crate_forced_target_does_not_get_overridden() { + per_crate_target_test( + None, + Some(cross_compile::alternate()), + Some(cross_compile::unused()), + ); +} + +#[cargo_test] +fn workspace_with_multiple_targets() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["native", "cross"] + "#, + ) + .file( + "native/Cargo.toml", + r#" + cargo-features = ["per-package-target"] + + [package] + name = "native" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "native/build.rs", + &format!( + r#" + fn main() {{ + assert_eq!(std::env::var("TARGET").unwrap(), "{}"); + }} + "#, + cross_compile::native() + ), + ) + .file( + "native/src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::native_arch() + ), + ) + .file( + "cross/Cargo.toml", + &format!( + r#" + cargo-features = ["per-package-target"] + + [package] + name = "cross" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + default-target = "{}" + "#, + cross_compile::alternate(), + ), + ) + .file( + "cross/build.rs", + &format!( + r#" + fn main() {{ + assert_eq!(std::env::var("TARGET").unwrap(), "{}"); + }} + "#, + cross_compile::alternate() + ), + ) + .file( + "cross/src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let mut cmd = p.cargo("build -v"); + cmd.masquerade_as_nightly_cargo(&["per-package-target"]) + .run(); + + assert!(p.bin("native").is_file()); + assert!(p.target_bin(cross_compile::alternate(), "cross").is_file()); + + p.process(&p.bin("native")).run(); + if cross_compile::can_run_on_host() { + p.process(&p.target_bin(cross_compile::alternate(), "cross")) + .run(); + } +} + +#[cargo_test] +fn linker() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + linker = "my-linker-tool" + "#, + target + ), + ) + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/foo.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + p.cargo("build -v --target") + .arg(&target) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] path `src/foo.rs` was erroneously implicitly accepted for binary `foo`, +please set bin.path in Cargo.toml +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/foo.rs [..]--crate-type bin --emit=[..]link[..]-C debuginfo=2 [..] -C metadata=[..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] -C linker=my-linker-tool -L dependency=[ROOT]/foo/target/[ALT_TARGET]/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[ERROR] linker `my-linker-tool` not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn cross_tests() { + if !cross_compile::can_run_on_host() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [[bin]] + name = "bar" + "#, + ) + .file( + "src/bin/bar.rs", + &format!( + r#" + #[allow(unused_extern_crates)] + extern crate foo; + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + #[test] fn test() {{ main() }} + "#, + cross_compile::alternate_arch() + ), + ) + .file( + "src/lib.rs", + &format!( + r#" + use std::env; + pub fn foo() {{ assert_eq!(env::consts::ARCH, "{}"); }} + #[test] fn test_foo() {{ foo() }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let target = cross_compile::alternate(); + p.cargo("test --target") + .arg(&target) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]) +[RUNNING] unittests src/bin/bar.rs (target/[ALT_TARGET]/debug/deps/bar-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test_foo ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn no_cross_doctests() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "src/lib.rs", + r#" + //! ``` + //! extern crate foo; + //! assert!(true); + //! ``` + "#, + ) + .build(); + + let host_output = "\ +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo +"; + + println!("a"); + p.cargo("test").with_stderr_data(host_output).run(); + + println!("b"); + let target = rustc_host(); + p.cargo("test -v --target") + .arg(&target) + // Unordered since the two `rustc` invocations happen concurrently. + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]--crate-type lib[..] +[RUNNING] `rustc --crate-name foo [..]--test[..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/[HOST_TARGET]/debug/deps/foo-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc [..]--target [HOST_TARGET][..]` + +"#]] + .unordered(), + ) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test src/lib.rs - (line 2) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + println!("c"); + let target = cross_compile::alternate(); + + // This will build the library, but does not build or run doc tests. + // This should probably be a warning or error. + p.cargo("test -v --doc --target") + .arg(&target) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported +See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information. + +"#]]) + .run(); + + if !cross_compile::can_run_on_host() { + return; + } + + // This tests the library, but does not run the doc tests. + p.cargo("test -v --target") + .arg(&target) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]--test[..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]` +[NOTE] skipping doctests for foo v0.0.1 ([ROOT]/foo) (lib), cross-compilation doctests are not yet supported +See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#doctest-xcompile for more information. + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_cargo_run() { + if !cross_compile::can_run_on_host() { + return; + } + + let p = project() + .file( + "src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let target = cross_compile::alternate(); + p.cargo("run --target").arg(&target).run(); +} + +#[cargo_test] +fn cross_with_a_build_script() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = 'build.rs' + "#, + ) + .file( + "build.rs", + &format!( + r#" + use std::env; + use std::path::PathBuf; + fn main() {{ + assert_eq!(env::var("TARGET").unwrap(), "{0}"); + let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + assert_eq!(path.file_name().unwrap().to_str().unwrap(), "out"); + path.pop(); + assert!(path.file_name().unwrap().to_str().unwrap() + .starts_with("foo-")); + path.pop(); + assert_eq!(path.file_name().unwrap().to_str().unwrap(), "build"); + path.pop(); + assert_eq!(path.file_name().unwrap().to_str().unwrap(), "debug"); + path.pop(); + assert_eq!(path.file_name().unwrap().to_str().unwrap(), "{0}"); + path.pop(); + assert_eq!(path.file_name().unwrap().to_str().unwrap(), "target"); + }} + "#, + target + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v --target") + .arg(&target) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..] build.rs [..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] [..] +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/main.rs [..] --target [ALT_TARGET] [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_script_needed_for_host_and_target() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = 'build.rs' + + [dependencies.d1] + path = "d1" + [build-dependencies.d2] + path = "d2" + "#, + ) + .file( + "build.rs", + r#" + #[allow(unused_extern_crates)] + extern crate d2; + fn main() { d2::d2(); } + "#, + ) + .file( + "src/main.rs", + " + #[allow(unused_extern_crates)] + extern crate d1; + fn main() { d1::d1(); } + ", + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.0" + edition = "2015" + authors = [] + build = 'build.rs' + "#, + ) + .file("d1/src/lib.rs", "pub fn d1() {}") + .file( + "d1/build.rs", + r#" + use std::env; + fn main() { + let target = env::var("TARGET").unwrap(); + let root = std::env::current_dir().unwrap(); + let root = root.parent().unwrap().join(format!("link-{target}")); + println!("cargo::rustc-flags=-L {}", root.display()); + } + "#, + ) + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "../d1" + "#, + ) + .file( + "d2/src/lib.rs", + " + #[allow(unused_extern_crates)] + extern crate d1; + pub fn d2() { d1::d1(); } + ", + ) + .build(); + p.root().join(format!("link-{target}")).mkdir_p(); + p.root().join(format!("link-{}", rustc_host())).mkdir_p(); + + p.cargo("build -v --target") + .arg(&target) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] d1 v0.0.0 ([ROOT]/foo/d1) +[RUNNING] `rustc [..] d1/build.rs [..] --out-dir [ROOT]/foo/target/debug/build/d1-[HASH] [..] +[RUNNING] `[ROOT]/foo/target/debug/build/d1-[HASH]/build-script-build` +[RUNNING] `[ROOT]/foo/target/debug/build/d1-[HASH]/build-script-build` +[RUNNING] `rustc [..] d1/src/lib.rs [..] --out-dir [ROOT]/foo/target/debug/deps [..] +[RUNNING] `rustc [..] d1/src/lib.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps [..] +[COMPILING] d2 v0.0.0 ([ROOT]/foo/d2) +[RUNNING] `rustc [..] d2/src/lib.rs [..] --out-dir [ROOT]/foo/target/debug/deps [..]-L [ROOT]/foo/link-[HOST_TARGET]` +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..] build.rs [..] --out-dir [ROOT]/foo/target/debug/build/foo-[HASH] [..]-L [ROOT]/foo/link-[HOST_TARGET]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/main.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] [..]-L [ROOT]/foo/link-[ALT_TARGET]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn build_deps_for_the_right_arch() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.d2] + path = "d2" + "#, + ) + .file("src/main.rs", "extern crate d2; fn main() {}") + .file("d1/Cargo.toml", &basic_manifest("d1", "0.0.0")) + .file("d1/src/lib.rs", "pub fn d1() {}") + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + + [build-dependencies.d1] + path = "../d1" + "#, + ) + .file("d2/build.rs", "extern crate d1; fn main() {}") + .file("d2/src/lib.rs", "") + .build(); + + let target = cross_compile::alternate(); + p.cargo("build -v --target").arg(&target).run(); +} + +#[cargo_test] +fn build_script_only_host() { + if cross_compile::disabled() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + + [build-dependencies.d1] + path = "d1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("build.rs", "extern crate d1; fn main() {}") + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("d1/src/lib.rs", "pub fn d1() {}") + .file( + "d1/build.rs", + r#" + use std::env; + + fn main() { + assert!(env::var("OUT_DIR").unwrap().replace("\\", "/") + .contains("target/debug/build/d1-"), + "bad: {:?}", env::var("OUT_DIR")); + } + "#, + ) + .build(); + + let target = cross_compile::alternate(); + p.cargo("build -v --target").arg(&target).run(); +} + +#[cargo_test] +fn build_script_with_platform_specific_dependencies() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + + [build-dependencies.d1] + path = "d1" + "#, + ) + .file( + "build.rs", + " + #[allow(unused_extern_crates)] + extern crate d1; + fn main() {} + ", + ) + .file("src/lib.rs", "") + .file( + "d1/Cargo.toml", + &format!( + r#" + [package] + name = "d1" + version = "0.0.0" + edition = "2015" + authors = [] + + [target.{}.dependencies] + d2 = {{ path = "../d2" }} + "#, + host + ), + ) + .file( + "d1/src/lib.rs", + "#[allow(unused_extern_crates)] extern crate d2;", + ) + .file("d2/Cargo.toml", &basic_manifest("d2", "0.0.0")) + .file("d2/src/lib.rs", "") + .build(); + + p.cargo("build -v --target") + .arg(&target) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] d2 v0.0.0 ([ROOT]/foo/d2) +[RUNNING] `rustc [..] d2/src/lib.rs [..]` +[COMPILING] d1 v0.0.0 ([ROOT]/foo/d1) +[RUNNING] `rustc [..] d1/src/lib.rs [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] build.rs [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] src/lib.rs [..] --target [ALT_TARGET] [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn platform_specific_dependencies_do_not_leak() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + + [dependencies.d1] + path = "d1" + + [build-dependencies.d1] + path = "d1" + "#, + ) + .file("build.rs", "extern crate d1; fn main() {}") + .file("src/lib.rs", "") + .file( + "d1/Cargo.toml", + &format!( + r#" + [package] + name = "d1" + version = "0.0.0" + edition = "2015" + authors = [] + + [target.{}.dependencies] + d2 = {{ path = "../d2" }} + "#, + host + ), + ) + .file("d1/src/lib.rs", "extern crate d2;") + .file("d1/Cargo.toml", &basic_manifest("d1", "0.0.0")) + .file("d2/src/lib.rs", "") + .build(); + + p.cargo("build -v --target") + .arg(&target) + .with_status(101) + .with_stderr_data(str![[r#" +... +error[E0463]: can't find crate for `d2` +... +"#]]) + .run(); +} + +#[cargo_test] +fn platform_specific_variables_reflected_in_build_scripts() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + + [target.{host}.dependencies] + d1 = {{ path = "d1" }} + + [target.{target}.dependencies] + d2 = {{ path = "d2" }} + "#, + host = host, + target = target + ), + ) + .file( + "build.rs", + &format!( + r#" + use std::env; + + fn main() {{ + let platform = env::var("TARGET").unwrap(); + let (expected, not_expected) = match &platform[..] {{ + "{host}" => ("DEP_D1_VAL", "DEP_D2_VAL"), + "{target}" => ("DEP_D2_VAL", "DEP_D1_VAL"), + _ => panic!("unknown platform") + }}; + + env::var(expected).ok() + .expect(&format!("missing {{}}", expected)); + env::var(not_expected).err() + .expect(&format!("found {{}}", not_expected)); + }} + "#, + host = host, + target = target + ), + ) + .file("src/lib.rs", "") + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.0" + edition = "2015" + authors = [] + links = "d1" + build = "build.rs" + "#, + ) + .file( + "d1/build.rs", + r#"fn main() { println!("cargo::metadata=val=1") }"#, + ) + .file("d1/src/lib.rs", "") + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.0" + edition = "2015" + authors = [] + links = "d2" + build = "build.rs" + "#, + ) + .file( + "d2/build.rs", + r#"fn main() { println!("cargo::metadata=val=1") }"#, + ) + .file("d2/src/lib.rs", "") + .build(); + + p.cargo("build -v").run(); + p.cargo("build -v --target").arg(&target).run(); +} + +#[cargo_test] +#[cfg_attr( + target_os = "macos", + ignore = "don't have a dylib cross target on macos" +)] +fn cross_test_dylib() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + crate-type = ["dylib"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar as the_bar; + + pub fn bar() { the_bar::baz(); } + + #[test] + fn foo() { bar(); } + "#, + ) + .file( + "tests/test.rs", + r#" + extern crate foo as the_foo; + + #[test] + fn foo() { the_foo::bar(); } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "bar" + crate-type = ["dylib"] + "#, + ) + .file( + "bar/src/lib.rs", + &format!( + r#" + use std::env; + pub fn baz() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + p.cargo("test --target") + .arg(&target) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]) +[RUNNING] tests/test.rs (target/[ALT_TARGET]/debug/deps/test-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test foo ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test foo ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")] +fn doctest_xcompile_linker() { + if cross_compile::disabled() { + return; + } + + let target = cross_compile::alternate(); + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + linker = "my-linker-tool" + "#, + target + ), + ) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file( + "src/lib.rs", + r#" + /// ``` + /// assert_eq!(1, 1); + /// ``` + pub fn foo() {} + "#, + ) + .build(); + + // Fails because `my-linker-tool` doesn't actually exist. + p.cargo("test --doc -v -Zdoctest-xcompile --target") + .arg(&target) + .with_status(101) + .masquerade_as_nightly_cargo(&["doctest-xcompile"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --out-dir [ROOT]/foo/target/[ALT_TARGET]/debug/deps --target [ALT_TARGET] [..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[DOCTEST] foo +[RUNNING] `rustdoc [..] src/lib.rs [..] +[ERROR] doctest failed, to rerun pass `--doc` + +"#]]) + .run(); +} + +#[cargo_test] +fn always_emit_warnings_as_warnings_when_learning_target_info() { + if cross_compile::disabled() { + return; + } + + let target = "wasm32-unknown-unknown"; + if !cross_compile::requires_target_installed(target) { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v --target") + .env("RUSTFLAGS", "-Awarnings") + .arg(target) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]-Awarnings[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_publish.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_publish.rs new file mode 100644 index 000000000..fa74669b4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/cross_publish.rs @@ -0,0 +1,123 @@ +//! Tests for publishing using the `--target` flag. + +use std::fs::File; + +use cargo_test_support::prelude::*; +use cargo_test_support::{cross_compile, project, publish, registry, str}; + +#[cargo_test] +fn simple_cross_package() { + if cross_compile::disabled() { + return; + } + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + repository = "bar" + "#, + ) + .file( + "src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let target = cross_compile::alternate(); + + p.cargo("package --target") + .arg(&target) + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.0 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.0 ([ROOT]/foo) +[COMPILING] foo v0.0.0 ([ROOT]/foo/target/package/foo-0.0.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Check that the tarball contains the files + let f = File::open(&p.root().join("target/package/foo-0.0.0.crate")).unwrap(); + publish::validate_crate_contents( + f, + "foo-0.0.0.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + (), + ); +} + +#[cargo_test] +fn publish_with_target() { + if cross_compile::disabled() { + return; + } + + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + repository = "bar" + "#, + ) + .file( + "src/main.rs", + &format!( + r#" + use std::env; + fn main() {{ + assert_eq!(env::consts::ARCH, "{}"); + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + let target = cross_compile::alternate(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .arg("--target") + .arg(&target) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.0.0 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.0 ([ROOT]/foo) +[COMPILING] foo v0.0.0 ([ROOT]/foo/target/package/foo-0.0.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.0 ([ROOT]/foo) +[UPLOADED] foo v0.0.0 to registry `crates-io` +[NOTE] waiting for `foo v0.0.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.0 at registry `crates-io` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/custom_target.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/custom_target.rs new file mode 100644 index 000000000..feafccf2a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/custom_target.rs @@ -0,0 +1,268 @@ +//! Tests for custom json target specifications. + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, project, str}; + +const MINIMAL_LIB: &str = r#" +#![allow(internal_features)] +#![feature(no_core)] +#![feature(lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized { + // Empty. +} +#[lang = "copy"] +pub trait Copy { + // Empty. +} +"#; + +const SIMPLE_SPEC: &str = r#" +{ + "llvm-target": "x86_64-unknown-none-gnu", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + "arch": "x86_64", + "target-endian": "little", + "target-pointer-width": "64", + "target-c-int-width": "32", + "os": "none", + "linker-flavor": "ld.lld", + "linker": "rust-lld", + "executables": true +} +"#; + +#[cargo_test(nightly, reason = "requires features no_core, lang_items")] +fn custom_target_minimal() { + let p = project() + .file( + "src/lib.rs", + &" + __MINIMAL_LIB__ + + pub fn foo() -> u32 { + 42 + } + " + .replace("__MINIMAL_LIB__", MINIMAL_LIB), + ) + .file("custom-target.json", SIMPLE_SPEC) + .build(); + + p.cargo("build --lib --target custom-target.json -v").run(); + p.cargo("build --lib --target src/../custom-target.json -v") + .run(); + + // Ensure that the correct style of flag is passed to --target with doc tests. + p.cargo("test --doc --target src/../custom-target.json -v -Zdoctest-xcompile") + .masquerade_as_nightly_cargo(&["doctest-xcompile", "no_core", "lang_items"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[DOCTEST] foo +[RUNNING] `rustdoc [..]--target [..]foo/custom-target.json[..] + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires features no_core, lang_items, auto_traits")] +fn custom_target_dependency() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.0.1" + edition = "2015" + authors = ["author@example.com"] + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + r#" + #![allow(internal_features)] + #![feature(no_core)] + #![feature(lang_items)] + #![feature(auto_traits)] + #![no_core] + + extern crate bar; + + pub fn foo() -> u32 { + bar::bar() + } + + #[lang = "freeze"] + unsafe auto trait Freeze {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "bar/src/lib.rs", + &" + __MINIMAL_LIB__ + + pub fn bar() -> u32 { + 42 + } + " + .replace("__MINIMAL_LIB__", MINIMAL_LIB), + ) + .file("custom-target.json", SIMPLE_SPEC) + .build(); + + p.cargo("build --lib --target custom-target.json -v").run(); +} + +#[cargo_test(nightly, reason = "requires features no_core, lang_items")] +// This is randomly crashing in lld. See https://github.com/rust-lang/rust/issues/115985 +#[cfg_attr(all(windows, target_env = "gnu"), ignore = "windows-gnu lld crashing")] +fn custom_bin_target() { + let p = project() + .file( + "src/main.rs", + &" + #![no_main] + __MINIMAL_LIB__ + " + .replace("__MINIMAL_LIB__", MINIMAL_LIB), + ) + .file("custom-bin-target.json", SIMPLE_SPEC) + .build(); + + p.cargo("build --target custom-bin-target.json -v").run(); +} + +#[cargo_test(nightly, reason = "requires features no_core, lang_items")] +fn changing_spec_rebuilds() { + // Changing the .json file will trigger a rebuild. + let p = project() + .file( + "src/lib.rs", + &" + __MINIMAL_LIB__ + + pub fn foo() -> u32 { + 42 + } + " + .replace("__MINIMAL_LIB__", MINIMAL_LIB), + ) + .file("custom-target.json", SIMPLE_SPEC) + .build(); + + p.cargo("build --lib --target custom-target.json -v").run(); + p.cargo("build --lib --target custom-target.json -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + let spec_path = p.root().join("custom-target.json"); + let spec = fs::read_to_string(&spec_path).unwrap(); + // Some arbitrary change that I hope is safe. + let spec = spec.replace('{', "{\n\"vendor\": \"unknown\",\n"); + fs::write(&spec_path, spec).unwrap(); + p.cargo("build --lib --target custom-target.json -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires features no_core, lang_items")] +// This is randomly crashing in lld. See https://github.com/rust-lang/rust/issues/115985 +#[cfg_attr(all(windows, target_env = "gnu"), ignore = "windows-gnu lld crashing")] +fn changing_spec_relearns_crate_types() { + // Changing the .json file will invalidate the cache of crate types. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["cdylib"] + "#, + ) + .file("src/lib.rs", MINIMAL_LIB) + .file("custom-target.json", SIMPLE_SPEC) + .build(); + + p.cargo("build --lib --target custom-target.json -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot produce cdylib for `foo v0.1.0 ([ROOT]/foo)` [..] + +"#]]) + .run(); + + // Enable dynamic linking. + let spec_path = p.root().join("custom-target.json"); + let spec = fs::read_to_string(&spec_path).unwrap(); + let spec = spec.replace('{', "{\n\"dynamic-linking\": true,\n"); + fs::write(&spec_path, spec).unwrap(); + + p.cargo("build --lib --target custom-target.json -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires features no_core, lang_items")] +fn custom_target_ignores_filepath() { + // Changing the path of the .json file will not trigger a rebuild. + let p = project() + .file( + "src/lib.rs", + &" + __MINIMAL_LIB__ + + pub fn foo() -> u32 { + 42 + } + " + .replace("__MINIMAL_LIB__", MINIMAL_LIB), + ) + .file("b/custom-target.json", SIMPLE_SPEC) + .file("a/custom-target.json", SIMPLE_SPEC) + .build(); + + // Should build the library the first time. + p.cargo("build --lib --target a/custom-target.json") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // But not the second time, even though the path to the custom target is dfferent. + p.cargo("build --lib --target b/custom-target.json") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/death.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/death.rs new file mode 100644 index 000000000..f57b74de5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/death.rs @@ -0,0 +1,102 @@ +//! Tests for ctrl-C handling. + +use std::fs; +use std::io::{self, Read}; +use std::net::TcpListener; +use std::process::{Child, Stdio}; +use std::thread; + +use cargo_test_support::prelude::*; +use cargo_test_support::{project, slow_cpu_multiplier}; + +#[cargo_test] +fn ctrl_c_kills_everyone() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + &format!( + r#" + use std::net::TcpStream; + use std::io::Read; + + fn main() {{ + let mut socket = TcpStream::connect("{}").unwrap(); + let _ = socket.read(&mut [0; 10]); + panic!("that read should never return"); + }} + "#, + addr + ), + ) + .build(); + + let mut cargo = p.cargo("check").build_command(); + cargo + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .env("__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE", "1"); + let mut child = cargo.spawn().unwrap(); + + let mut sock = listener.accept().unwrap().0; + ctrl_c(&mut child); + + assert!(!child.wait().unwrap().success()); + match sock.read(&mut [0; 10]) { + Ok(n) => assert_eq!(n, 0), + Err(e) => assert_eq!(e.kind(), io::ErrorKind::ConnectionReset), + } + + // Ok so what we just did was spawn cargo that spawned a build script, then + // we killed cargo in hopes of it killing the build script as well. If all + // went well the build script is now dead. On Windows, however, this is + // enforced with job objects which means that it may actually be in the + // *process* of being torn down at this point. + // + // Now on Windows we can't completely remove a file until all handles to it + // have been closed. Including those that represent running processes. So if + // we were to return here then there may still be an open reference to some + // file in the build directory. What we want to actually do is wait for the + // build script to *complete* exit. Take care of that by blowing away the + // build directory here, and panicking if we eventually spin too long + // without being able to. + for i in 0..10 { + match fs::remove_dir_all(&p.root().join("target")) { + Ok(()) => return, + Err(e) => println!("attempt {}: {}", i, e), + } + thread::sleep(slow_cpu_multiplier(100)); + } + + panic!( + "couldn't remove build directory after a few tries, seems like \ + we won't be able to!" + ); +} + +#[cfg(unix)] +pub fn ctrl_c(child: &mut Child) { + let r = unsafe { libc::kill(-(child.id() as i32), libc::SIGINT) }; + if r < 0 { + panic!("failed to kill: {}", io::Error::last_os_error()); + } +} + +#[cfg(windows)] +pub fn ctrl_c(child: &mut Child) { + child.kill().unwrap(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/dep_info.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/dep_info.rs new file mode 100644 index 000000000..8104f62ba --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/dep_info.rs @@ -0,0 +1,554 @@ +//! Tests for dep-info files. This includes the dep-info file Cargo creates in +//! the output directory, and the ones stored in the fingerprint. + +use std::path::Path; + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{assert_deps, assert_deps_contains}; +use cargo_test_support::{basic_bin_manifest, basic_manifest, main_file, project, rustc_host}; +use filetime::FileTime; + +#[cargo_test] +fn build_dep_info() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("build").run(); + + let depinfo_bin_path = &p.bin("foo").with_extension("d"); + + assert!(depinfo_bin_path.is_file()); + + let depinfo = p.read_file(depinfo_bin_path); + + let bin_path = p.bin("foo"); + let src_path = p.root().join("src").join("foo.rs"); + if !depinfo.lines().any(|line| { + line.starts_with(&format!("{}:", bin_path.display())) + && line.contains(src_path.to_str().unwrap()) + }) { + panic!( + "Could not find {:?}: {:?} in {:?}", + bin_path, src_path, depinfo_bin_path + ); + } +} + +#[cargo_test] +fn build_dep_info_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [[example]] + name = "ex" + crate-type = ["lib"] + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("build --example=ex").run(); + assert!(p.example_lib("ex", "lib").with_extension("d").is_file()); +} + +#[cargo_test] +fn build_dep_info_rlib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [[example]] + name = "ex" + crate-type = ["rlib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("build --example=ex").run(); + assert!(p.example_lib("ex", "rlib").with_extension("d").is_file()); +} + +#[cargo_test] +fn build_dep_info_dylib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [[example]] + name = "ex" + crate-type = ["dylib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("build --example=ex").run(); + assert!(p.example_lib("ex", "dylib").with_extension("d").is_file()); +} + +#[cargo_test] +fn dep_path_inside_target_has_correct_path() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("a")) + .file("target/debug/blah", "") + .file( + "src/main.rs", + r#" + fn main() { + let x = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/target/debug/blah")); + } + "#, + ) + .build(); + + p.cargo("build").run(); + + let depinfo_path = &p.bin("a").with_extension("d"); + + assert!(depinfo_path.is_file(), "{:?}", depinfo_path); + + let depinfo = p.read_file(depinfo_path); + + let bin_path = p.bin("a"); + let target_debug_blah = Path::new("target").join("debug").join("blah"); + if !depinfo.lines().any(|line| { + line.starts_with(&format!("{}:", bin_path.display())) + && line.contains(target_debug_blah.to_str().unwrap()) + }) { + panic!( + "Could not find {:?}: {:?} in {:?}", + bin_path, target_debug_blah, depinfo_path + ); + } +} + +#[cargo_test] +fn no_rewrite_if_no_change() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("build").run(); + let dep_info = p.root().join("target/debug/libfoo.d"); + let metadata1 = dep_info.metadata().unwrap(); + p.cargo("build").run(); + let metadata2 = dep_info.metadata().unwrap(); + + assert_eq!( + FileTime::from_last_modification_time(&metadata1), + FileTime::from_last_modification_time(&metadata2), + ); +} + +#[cargo_test(nightly, reason = "-Z binary-dep-depinfo is unstable")] +fn relative_depinfo_paths_ws() { + // Test relative dep-info paths in a workspace with --target with + // proc-macros and other dependency kinds. + Package::new("regdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + Package::new("pmdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + Package::new("bdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + + let p = project() + /*********** Workspace ***********/ + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + /*********** Main Project ***********/ + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + pm = {path = "../pm"} + bar = {path = "../bar"} + regdep = "0.1" + + [build-dependencies] + bdep = "0.1" + bar = {path = "../bar"} + "#, + ) + .file( + "foo/src/main.rs", + r#" + pm::noop!{} + + fn main() { + bar::f(); + regdep::f(); + } + "#, + ) + .file("foo/build.rs", "fn main() { bdep::f(); }") + /*********** Proc Macro ***********/ + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2018" + + [lib] + proc-macro = true + + [dependencies] + pmdep = "0.1" + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro] + pub fn noop(_item: TokenStream) -> TokenStream { + pmdep::f(); + "".parse().unwrap() + } + "#, + ) + /*********** Path Dependency `bar` ***********/ + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn f() {}") + .build(); + + let host = rustc_host(); + p.cargo("build -Z binary-dep-depinfo --target") + .arg(&host) + .masquerade_as_nightly_cargo(&["binary-dep-depinfo"]) + .with_stderr_data(str![[r#" +... +[COMPILING] foo v0.1.0 ([ROOT]/foo/foo) +... +"#]]) + .run(); + + assert_deps_contains( + &p, + "target/debug/.fingerprint/pm-*/dep-lib-pm", + &[(0, "src/lib.rs"), (1, "debug/deps/libpmdep-*.rlib")], + ); + + assert_deps_contains( + &p, + &format!("target/{}/debug/.fingerprint/foo-*/dep-bin-foo", host), + &[ + (0, "src/main.rs"), + ( + 1, + &format!( + "debug/deps/{}pm-*.{}", + paths::get_lib_prefix("proc-macro"), + paths::get_lib_extension("proc-macro") + ), + ), + (1, &format!("{}/debug/deps/libbar-*.rlib", host)), + (1, &format!("{}/debug/deps/libregdep-*.rlib", host)), + ], + ); + + assert_deps_contains( + &p, + "target/debug/.fingerprint/foo-*/dep-build-script-build-script-build", + &[(0, "build.rs"), (1, "debug/deps/libbdep-*.rlib")], + ); + + // Make sure it stays fresh. + p.cargo("build -Z binary-dep-depinfo --target") + .arg(&host) + .masquerade_as_nightly_cargo(&["binary-dep-depinfo"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Z binary-dep-depinfo is unstable")] +fn relative_depinfo_paths_no_ws() { + // Test relative dep-info paths without a workspace with proc-macros and + // other dependency kinds. + Package::new("regdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + Package::new("pmdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + Package::new("bdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + + let p = project() + /*********** Main Project ***********/ + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + pm = {path = "pm"} + bar = {path = "bar"} + regdep = "0.1" + + [build-dependencies] + bdep = "0.1" + bar = {path = "bar"} + "#, + ) + .file( + "src/main.rs", + r#" + pm::noop!{} + + fn main() { + bar::f(); + regdep::f(); + } + "#, + ) + .file("build.rs", "fn main() { bdep::f(); }") + /*********** Proc Macro ***********/ + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2018" + + [lib] + proc-macro = true + + [dependencies] + pmdep = "0.1" + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro] + pub fn noop(_item: TokenStream) -> TokenStream { + pmdep::f(); + "".parse().unwrap() + } + "#, + ) + /*********** Path Dependency `bar` ***********/ + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn f() {}") + .build(); + + p.cargo("build -Z binary-dep-depinfo") + .masquerade_as_nightly_cargo(&["binary-dep-depinfo"]) + .with_stderr_data(str![[r#" +... +[COMPILING] foo v0.1.0 ([ROOT]/foo) +... +"#]]) + .run(); + + assert_deps_contains( + &p, + "target/debug/.fingerprint/pm-*/dep-lib-pm", + &[(0, "src/lib.rs"), (1, "debug/deps/libpmdep-*.rlib")], + ); + + assert_deps_contains( + &p, + "target/debug/.fingerprint/foo-*/dep-bin-foo", + &[ + (0, "src/main.rs"), + ( + 1, + &format!( + "debug/deps/{}pm-*.{}", + paths::get_lib_prefix("proc-macro"), + paths::get_lib_extension("proc-macro") + ), + ), + (1, "debug/deps/libbar-*.rlib"), + (1, "debug/deps/libregdep-*.rlib"), + ], + ); + + assert_deps_contains( + &p, + "target/debug/.fingerprint/foo-*/dep-build-script-build-script-build", + &[(0, "build.rs"), (1, "debug/deps/libbdep-*.rlib")], + ); + + // Make sure it stays fresh. + p.cargo("build -Z binary-dep-depinfo") + .masquerade_as_nightly_cargo(&["binary-dep-depinfo"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn reg_dep_source_not_tracked() { + // Make sure source files in dep-info file are not tracked for registry dependencies. + Package::new("regdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + regdep = "0.1" + "#, + ) + .file("src/lib.rs", "pub fn f() { regdep::f(); }") + .build(); + + p.cargo("check").run(); + + assert_deps( + &p, + "target/debug/.fingerprint/regdep-*/dep-lib-regdep", + |info_path, entries| { + for (kind, path) in entries { + if *kind == 1 { + panic!( + "Did not expect package root relative path type: {:?} in {:?}", + path, info_path + ); + } + } + }, + ); +} + +#[cargo_test(nightly, reason = "-Z binary-dep-depinfo is unstable")] +fn canonical_path() { + if !cargo_test_support::symlink_supported() { + return; + } + Package::new("regdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + regdep = "0.1" + "#, + ) + .file("src/lib.rs", "pub fn f() { regdep::f(); }") + .build(); + + let real = p.root().join("real_target"); + real.mkdir_p(); + p.symlink(real, "target"); + + p.cargo("check -Z binary-dep-depinfo") + .masquerade_as_nightly_cargo(&["binary-dep-depinfo"]) + .run(); + + assert_deps_contains( + &p, + "target/debug/.fingerprint/foo-*/dep-lib-foo", + &[(0, "src/lib.rs"), (1, "debug/deps/libregdep-*.rmeta")], + ); +} + +#[cargo_test] +fn non_local_build_script() { + // Non-local build script information is not included. + Package::new("bar", "1.0.0") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + } + "#, + ) + .file("src/lib.rs", "") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); + let contents = p.read_file("target/debug/foo.d"); + assert_e2e().eq( + &contents, + str![[r#" +[ROOT]/foo/target/debug/foo[EXE]: [ROOT]/foo/src/main.rs + +"#]], + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/diagnostics.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/diagnostics.rs new file mode 100644 index 000000000..8bbebf0b7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/diagnostics.rs @@ -0,0 +1,33 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn dont_panic_on_render() { + let p = project() + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.1.0" +edition = "2021" +[[bench.foo]] +"#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: map, expected a sequence + --> Cargo.toml:6:3 + | +6 | [[bench.foo]] + | ^^^^^ + | + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/direct_minimal_versions.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/direct_minimal_versions.rs new file mode 100644 index 000000000..ec5e5f53e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/direct_minimal_versions.rs @@ -0,0 +1,256 @@ +//! Tests for minimal-version resolution. +//! +//! Note: Some tests are located in the resolver-tests package. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +#[cargo_test] +fn simple() { + Package::new("dep", "1.0.0").publish(); + Package::new("dep", "1.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies] + dep = "1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile -Zdirect-minimal-versions") + .masquerade_as_nightly_cargo(&["direct-minimal-versions"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package +[ADDING] dep v1.0.0 (available: v1.1.0) + +"#]]) + .run(); + + let lock = p.read_lockfile(); + + assert!( + lock.contains("1.0.0"), + "dep minimal version must be present" + ); + assert!( + !lock.contains("1.1.0"), + "dep maximimal version cannot be present" + ); +} + +#[cargo_test] +fn mixed_dependencies() { + Package::new("dep", "1.0.0").publish(); + Package::new("dep", "1.1.0").publish(); + Package::new("dep", "1.2.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies] + dep = "1.0" + + [dev-dependencies] + dep = "1.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile -Zdirect-minimal-versions") + .masquerade_as_nightly_cargo(&["direct-minimal-versions"]) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for `dep`. + ... required by package `foo v0.0.1 ([ROOT]/foo)` +versions that meet the requirements `^1.1` are: 1.1.0 + +all possible versions conflict with previously selected packages. + + previously selected package `dep v1.0.0` + ... which satisfies dependency `dep = "^1.0"` of package `foo v0.0.1 ([ROOT]/foo)` + +failed to select a version for `dep` which could resolve this conflict + +"#]]) + .run(); +} + +#[cargo_test] +fn yanked() { + Package::new("dep", "1.0.0").yanked(true).publish(); + Package::new("dep", "1.1.0").publish(); + Package::new("dep", "1.2.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies] + dep = "1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile -Zdirect-minimal-versions") + .masquerade_as_nightly_cargo(&["direct-minimal-versions"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package +[ADDING] dep v1.1.0 (available: v1.2.0) + +"#]]) + .run(); + + let lock = p.read_lockfile(); + + assert!( + lock.contains("1.1.0"), + "dep minimal version must be present" + ); + assert!( + !lock.contains("1.0.0"), + "yanked minimal version must be skipped" + ); + assert!( + !lock.contains("1.2.0"), + "dep maximimal version cannot be present" + ); +} + +#[cargo_test] +fn indirect() { + Package::new("indirect", "2.0.0").publish(); + Package::new("indirect", "2.1.0").publish(); + Package::new("indirect", "2.2.0").publish(); + Package::new("direct", "1.0.0") + .dep("indirect", "2.1") + .publish(); + Package::new("direct", "1.1.0") + .dep("indirect", "2.1") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies] + direct = "1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile -Zdirect-minimal-versions") + .masquerade_as_nightly_cargo(&["direct-minimal-versions"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages +[ADDING] direct v1.0.0 (available: v1.1.0) + +"#]]) + .run(); + + let lock = p.read_lockfile(); + + assert!( + lock.contains("1.0.0"), + "direct minimal version must be present" + ); + assert!( + !lock.contains("1.1.0"), + "direct maximimal version cannot be present" + ); + assert!( + !lock.contains("2.0.0"), + "indirect minimal version cannot be present" + ); + assert!( + !lock.contains("2.1.0"), + "indirect minimal version cannot be present" + ); + assert!( + lock.contains("2.2.0"), + "indirect maximal version must be present" + ); +} + +#[cargo_test] +fn indirect_conflict() { + Package::new("indirect", "2.0.0").publish(); + Package::new("indirect", "2.1.0").publish(); + Package::new("indirect", "2.2.0").publish(); + Package::new("direct", "1.0.0") + .dep("indirect", "2.1") + .publish(); + Package::new("direct", "1.1.0") + .dep("indirect", "2.1") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies] + direct = "1.0" + indirect = "2.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile -Zdirect-minimal-versions") + .masquerade_as_nightly_cargo(&["direct-minimal-versions"]) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for `indirect`. + ... required by package `direct v1.0.0` + ... which satisfies dependency `direct = "^1.0"` of package `foo v0.0.1 ([ROOT]/foo)` +versions that meet the requirements `^2.1` are: 2.2.0, 2.1.0 + +all possible versions conflict with previously selected packages. + + previously selected package `indirect v2.0.0` + ... which satisfies dependency `indirect = "^2.0"` of package `foo v0.0.1 ([ROOT]/foo)` + +failed to select a version for `indirect` which could resolve this conflict + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/directory.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/directory.rs new file mode 100644 index 000000000..9e3f4fed5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/directory.rs @@ -0,0 +1,866 @@ +//! Tests for directory sources. + +use std::collections::HashMap; +use std::fs; +use std::str; + +use cargo_test_support::cargo_process; +use cargo_test_support::git; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{cksum, Package}; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, project, t, ProjectBuilder}; +use serde::Serialize; + +fn setup() { + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config.toml"), + r#" + [source.crates-io] + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'index' + "# + )); +} + +struct VendorPackage { + p: Option, + cksum: Checksum, +} + +#[derive(Serialize)] +struct Checksum { + package: Option, + files: HashMap, +} + +impl VendorPackage { + fn new(name: &str) -> VendorPackage { + VendorPackage { + p: Some(project().at(&format!("index/{}", name))), + cksum: Checksum { + package: Some(String::new()), + files: HashMap::new(), + }, + } + } + + fn file(&mut self, name: &str, contents: &str) -> &mut VendorPackage { + self.p = Some(self.p.take().unwrap().file(name, contents)); + self.cksum + .files + .insert(name.to_string(), cksum(contents.as_bytes())); + self + } + + fn disable_checksum(&mut self) -> &mut VendorPackage { + self.cksum.package = None; + self + } + + fn no_manifest(mut self) -> Self { + self.p = self.p.map(|pb| pb.no_manifest()); + self + } + + fn build(&mut self) { + let p = self.p.take().unwrap(); + let json = serde_json::to_string(&self.cksum).unwrap(); + let p = p.file(".cargo-checksum.json", &json); + let _ = p.build(); + } +} + +#[cargo_test] +fn simple() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn bar() {}") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_install() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.0.1" + "#, + ) + .file( + "src/main.rs", + "extern crate foo; pub fn main() { foo::foo(); }", + ) + .build(); + + cargo_process("install bar") + .with_stderr_data(str![[r#" +[INSTALLING] bar v0.1.0 +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.1 +[COMPILING] bar v0.1.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [..]bar[..] +[INSTALLED] package `bar v0.1.0` (executable `bar[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_install_fail() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.1.0" + baz = "9.8.7" + "#, + ) + .file( + "src/main.rs", + "extern crate foo; pub fn main() { foo::foo(); }", + ) + .build(); + + cargo_process("install bar") + .with_status(101) + .with_stderr_data(str![[r#" +[INSTALLING] bar v0.1.0 +[ERROR] failed to compile `bar v0.1.0`, intermediate artifacts can be found at `[..]`. +To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path. + +Caused by: + no matching package found + searched package name: `baz` + perhaps you meant: bar or foo + location searched: directory source `[ROOT]/index` (which is replacing registry `crates-io`) + required by package `bar v0.1.0` + +"#]]) + .run(); +} + +#[cargo_test] +fn install_without_feature_dep() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.0.1" + baz = { version = "9.8.7", optional = true } + + [features] + wantbaz = ["baz"] + "#, + ) + .file( + "src/main.rs", + "extern crate foo; pub fn main() { foo::foo(); }", + ) + .build(); + + cargo_process("install bar") + .with_stderr_data(str![[r#" +[INSTALLING] bar v0.1.0 +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.1 +[COMPILING] bar v0.1.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [..]bar[..] +[INSTALLED] package `bar v0.1.0` (executable `bar[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn not_there() { + setup(); + + let _ = project().at("index").build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no matching package named `bar` found +location searched: directory source `[ROOT]/index` (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple() { + setup(); + + VendorPackage::new("bar-0.1.0") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn bar() {}") + .file(".cargo-checksum", "") + .build(); + + VendorPackage::new("bar-0.2.0") + .file("Cargo.toml", &basic_manifest("bar", "0.2.0")) + .file("src/lib.rs", "pub fn bar() {}") + .file(".cargo-checksum", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.0 (available: v0.2.0) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn crates_io_then_directory() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + let cksum = Package::new("bar", "0.1.0") + .file("src/lib.rs", "pub fn bar() -> u32 { 0 }") + .publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + setup(); + + let mut v = VendorPackage::new("bar"); + v.file("Cargo.toml", &basic_manifest("bar", "0.1.0")); + v.file("src/lib.rs", "pub fn bar() -> u32 { 1 }"); + v.cksum.package = Some(cksum); + v.build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn crates_io_then_bad_checksum() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("bar", "0.1.0").publish(); + + p.cargo("check").run(); + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] checksum for `bar v0.1.0` changed between lock files + +this could be indicative of a few possible errors: + + * the lock file is corrupt + * a replacement source in use (e.g., a mirror) returned a different checksum + * the source itself may be corrupt in one way or another + +unable to verify that `bar v0.1.0` is the same as when the lockfile was generated + + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_file_checksum() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + t!(fs::write( + paths::root().join("index/bar/src/lib.rs"), + "fn bar() -> u32 { 0 }" + )); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] the listed checksum of `[ROOT]/index/bar/src/lib.rs` has changed: +expected: [..] +actual: [..] + +directory sources are not intended to be edited, if modifications are required then it is recommended that `[patch]` is used with a forked copy of the source + +"#]]) + .run(); +} + +#[cargo_test] +fn only_dot_files_ok() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + VendorPackage::new("foo") + .no_manifest() + .file(".bar", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn random_files_ok() { + setup(); + + VendorPackage::new("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + VendorPackage::new("foo") + .no_manifest() + .file("bar", "") + .file("../test", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn git_lock_file_doesnt_change() { + let git = git::new("git", |p| { + p.file("Cargo.toml", &basic_manifest("git", "0.5.0")) + .file("src/lib.rs", "") + }); + + VendorPackage::new("git") + .file("Cargo.toml", &basic_manifest("git", "0.5.0")) + .file("src/lib.rs", "") + .disable_checksum() + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + git = {{ git = '{0}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + let lock1 = p.read_lockfile(); + + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config.toml"), + format!( + r#" + [source.my-git-repo] + git = '{}' + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'index' + "#, + git.url() + ) + )); + + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] git v0.5.0 ([..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let lock2 = p.read_lockfile(); + assert_eq!(lock1, lock2, "lock files changed"); +} + +#[cargo_test] +fn git_override_requires_lockfile() { + VendorPackage::new("git") + .file("Cargo.toml", &basic_manifest("git", "0.5.0")) + .file("src/lib.rs", "") + .disable_checksum() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + git = { git = 'https://example.com/' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config.toml"), + r#" + [source.my-git-repo] + git = 'https://example.com/' + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'index' + "# + )); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `git` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `git` + +Caused by: + Unable to update [..] + +Caused by: + the source my-git-repo requires a lock file to be present first before it can be + used against vendored source code + + remove the source replacement configuration, generate a lock file, and then + restore the source replacement configuration to continue the build + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_different_locations() { + let p = project() + .no_manifest() + .file( + "foo/Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = "2015" + + [dependencies] + baz = "*" + "#, + ) + .file("foo/src/lib.rs", "") + .file("foo/vendor/baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("foo/vendor/baz/src/lib.rs", "") + .file("foo/vendor/baz/.cargo-checksum.json", "{\"files\":{}}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = 'bar' + version = '0.1.0' + edition = "2015" + + [dependencies] + baz = "*" + "#, + ) + .file("bar/src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = './target' + + [source.crates-io] + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + directory = 'foo/vendor' + "#, + ) + .build(); + + p.cargo("check").cwd("foo").run(); + p.cargo("check") + .cwd("bar") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn version_missing() { + setup(); + + VendorPackage::new("foo") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + VendorPackage::new("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + cargo_process("install bar") + .with_stderr_data(str![[r#" +[INSTALLING] bar v0.1.0 +[ERROR] failed to compile [..], intermediate artifacts can be found at `[..]`. +To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path. + +Caused by: + failed to select a version for the requirement `foo = "^2"` + candidate versions found which didn't match: 0.0.1 + location searched: directory source `[..] (which is replacing registry `[..]`) + required by package `bar v0.1.0` + perhaps a crate was updated and forgotten to be re-vendored? + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn root_dir_diagnostics() { + let p = ProjectBuilder::new(paths::root()) + .no_manifest() // we are placing it in a different dir + .file( + "ws_root/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file("ws_root/src/lib.rs", "invalid;") + .build(); + + // Crucially, the rustc error message below says `ws_root/...`, i.e. + // it is relative to our fake home, not to the workspace root. + p.cargo("check") + .arg("-Zroot-dir=.") + .arg("--manifest-path=ws_root/Cargo.toml") + .masquerade_as_nightly_cargo(&["-Zroot-dir"]) + .with_status(101) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/ws_root) +[ERROR] [..] + --> ws_root/src/lib.rs:1:8 + | +1 | invalid; + | [..] + +[ERROR] could not compile `foo` (lib) due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test] +fn root_dir_file_macro() { + let p = ProjectBuilder::new(paths::root()) + .no_manifest() // we are placing it in a different dir + .file( + "ws_root/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file( + "ws_root/src/main.rs", + r#"fn main() { println!("{}", file!()); }"#, + ) + .build(); + + // Crucially, the path is relative to our fake home, not to the workspace root. + p.cargo("run") + .arg("-Zroot-dir=.") + .arg("--manifest-path=ws_root/Cargo.toml") + .masquerade_as_nightly_cargo(&["-Zroot-dir"]) + .with_stdout_data(str![[r#" +ws_root/src/main.rs + +"#]]) + .run(); + // Try again with an absolute path for `root-dir`. + p.cargo("run") + .arg(format!("-Zroot-dir={}", p.root().display())) + .arg("--manifest-path=ws_root/Cargo.toml") + .masquerade_as_nightly_cargo(&["-Zroot-dir"]) + .with_stdout_data(str![[r#" +ws_root/src/main.rs + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/doc.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/doc.rs new file mode 100644 index 000000000..fcaa553f0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/doc.rs @@ -0,0 +1,2899 @@ +//! Tests for the `cargo doc` command. + +use std::fs; +use std::str; + +use cargo::core::compiler::RustDocFingerprint; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project}; +use cargo_test_support::{rustc_host, symlink_supported, tools}; + +#[cargo_test] +fn simple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); +} + +#[cargo_test] +fn doc_no_libs() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "foo" + doc = false + "#, + ) + .file("src/main.rs", "bad code") + .build(); + + p.cargo("doc").run(); +} + +#[cargo_test] +fn doc_twice() { + let p = project().file("src/lib.rs", "pub fn foo() {}").build(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/lib.rs", "extern crate bar; pub fn foo() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("doc") + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar) +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!(p.root().join("target/doc/bar/index.html").is_file()); + + // Verify that it only emits rmeta for the dependency. + assert_eq!(p.glob("target/debug/**/*.rlib").count(), 0); + assert_eq!(p.glob("target/debug/deps/libbar-*.rmeta").count(), 1); + + // Make sure it doesn't recompile. + p.cargo("doc") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!(p.root().join("target/doc/bar/index.html").is_file()); +} + +#[cargo_test] +fn doc_no_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/lib.rs", "extern crate bar; pub fn foo() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("doc --no-deps") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!(!p.root().join("target/doc/bar/index.html").is_file()); +} + +#[cargo_test] +fn doc_only_bin() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "extern crate bar; pub fn foo() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("doc -v").run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/bar/index.html").is_file()); + assert!(p.root().join("target/doc/foo/index.html").is_file()); +} + +#[cargo_test] +fn doc_multiple_targets_same_name_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + name = "foo_lib" + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + [lib] + name = "foo_lib" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("doc --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] document output filename collision +The lib `foo_lib` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same name as the lib `foo_lib` in package `bar v0.1.0 ([ROOT]/foo/bar)`. +Only one may be documented at once since they output to the same path. +Consider documenting only one, renaming one, or marking one with `doc = false` in Cargo.toml. + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_multiple_targets_same_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [[bin]] + name = "foo_lib" + path = "src/foo_lib.rs" + "#, + ) + .file("foo/src/foo_lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + [lib] + name = "foo_lib" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("doc --workspace") + .with_stderr_data(str![[r#" +[WARNING] output filename collision. +The bin target `foo_lib` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same output filename as the lib target `foo_lib` in package `bar v0.1.0 ([ROOT]/foo/bar)`. +Colliding filename is: [ROOT]/foo/target/doc/foo_lib/index.html +The targets should have unique names. +This is a known bug where multiple crates with the same name use +the same path; see . +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo_lib/index.html and 1 other file + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn doc_multiple_targets_same_name_bin() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("foo/src/bin/foo-cli.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("bar/src/bin/foo-cli.rs", "") + .build(); + + p.cargo("doc --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] document output filename collision +The bin `foo-cli` in package `foo v0.1.0 ([ROOT]/foo/foo)` has the same name as the bin `foo-cli` in package `bar v0.1.0 ([ROOT]/foo/bar)`. +Only one may be documented at once since they output to the same path. +Consider documenting only one, renaming one, or marking one with `doc = false` in Cargo.toml. + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_multiple_targets_same_name_undoced() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [[bin]] + name = "foo-cli" + "#, + ) + .file("foo/src/foo-cli.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + [[bin]] + name = "foo-cli" + doc = false + "#, + ) + .file("bar/src/foo-cli.rs", "") + .build(); + + p.cargo("doc --workspace").run(); +} + +#[cargo_test] +fn doc_lib_bin_same_name_documents_lib() { + let p = project() + .file( + "src/main.rs", + r#" + //! Binary documentation + extern crate foo; + fn main() { + foo::foo(); + } + "#, + ) + .file( + "src/lib.rs", + r#" + //! Library documentation + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let doc_html = p.read_file("target/doc/foo/index.html"); + assert!(doc_html.contains("Library")); + assert!(!doc_html.contains("Binary")); +} + +#[cargo_test] +fn doc_lib_bin_same_name_documents_lib_when_requested() { + let p = project() + .file( + "src/main.rs", + r#" + //! Binary documentation + extern crate foo; + fn main() { + foo::foo(); + } + "#, + ) + .file( + "src/lib.rs", + r#" + //! Library documentation + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("doc --lib") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let doc_html = p.read_file("target/doc/foo/index.html"); + assert!(doc_html.contains("Library")); + assert!(!doc_html.contains("Binary")); +} + +#[cargo_test] +fn doc_lib_bin_same_name_with_dash() { + // Checks `doc` behavior when there is a dash in the package name, and + // there is a lib and bin, and the lib name is inferred. + let p = project() + .file("Cargo.toml", &basic_manifest("foo-bar", "1.0.0")) + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("doc") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo-bar v1.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo_bar/index.html + +"#]]) + .run(); + assert!(p.build_dir().join("doc/foo_bar/index.html").exists()); + assert!(!p.build_dir().join("doc/foo_bar/fn.main.html").exists()); +} + +#[cargo_test] +fn doc_lib_bin_same_name_documents_named_bin_when_requested() { + let p = project() + .file( + "src/main.rs", + r#" + //! Binary documentation + extern crate foo; + fn main() { + foo::foo(); + } + "#, + ) + .file( + "src/lib.rs", + r#" + //! Library documentation + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("doc --bin foo") + // The checking/documenting lines are sometimes swapped since they run + // concurrently. + .with_stderr_data(str![[r#" +[WARNING] output filename collision. +The bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`. +Colliding filename is: [ROOT]/foo/target/doc/foo/index.html +The targets should have unique names. +This is a known bug where multiple crates with the same name use +the same path; see . +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]].unordered()) + .run(); + let doc_html = p.read_file("target/doc/foo/index.html"); + assert!(!doc_html.contains("Library")); + assert!(doc_html.contains("Binary")); +} + +#[cargo_test] +fn doc_lib_bin_same_name_documents_bins_when_requested() { + let p = project() + .file( + "src/main.rs", + r#" + //! Binary documentation + extern crate foo; + fn main() { + foo::foo(); + } + "#, + ) + .file( + "src/lib.rs", + r#" + //! Library documentation + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("doc --bins") + // The checking/documenting lines are sometimes swapped since they run + // concurrently. + .with_stderr_data(str![[r#" +[WARNING] output filename collision. +The bin target `foo` in package `foo v0.0.1 ([ROOT]/foo)` has the same output filename as the lib target `foo` in package `foo v0.0.1 ([ROOT]/foo)`. +Colliding filename is: [ROOT]/foo/target/doc/foo/index.html +The targets should have unique names. +This is a known bug where multiple crates with the same name use +the same path; see . +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]].unordered()) + .run(); + let doc_html = p.read_file("target/doc/foo/index.html"); + assert!(!doc_html.contains("Library")); + assert!(doc_html.contains("Binary")); +} + +#[cargo_test] +fn doc_lib_bin_example_same_name_documents_named_example_when_requested() { + let p = project() + .file( + "src/main.rs", + r#" + //! Binary documentation + extern crate foo; + fn main() { + foo::foo(); + } + "#, + ) + .file( + "src/lib.rs", + r#" + //! Library documentation + pub fn foo() {} + "#, + ) + .file( + "examples/ex1.rs", + r#" + //! Example1 documentation + pub fn x() { f(); } + "#, + ) + .build(); + + p.cargo("doc --example ex1") + // The checking/documenting lines are sometimes swapped since they run + // concurrently. + .with_stderr_data( + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/ex1/index.html + +"#]] + .unordered(), + ) + .run(); + + let doc_html = p.read_file("target/doc/ex1/index.html"); + assert!(!doc_html.contains("Library")); + assert!(!doc_html.contains("Binary")); + assert!(doc_html.contains("Example1")); +} + +#[cargo_test] +fn doc_lib_bin_example_same_name_documents_examples_when_requested() { + let p = project() + .file( + "src/main.rs", + r#" + //! Binary documentation + extern crate foo; + fn main() { + foo::foo(); + } + "#, + ) + .file( + "src/lib.rs", + r#" + //! Library documentation + pub fn foo() {} + "#, + ) + .file( + "examples/ex1.rs", + r#" + //! Example1 documentation + pub fn example1() { f(); } + "#, + ) + .file( + "examples/ex2.rs", + r#" + //! Example2 documentation + pub fn example2() { f(); } + "#, + ) + .build(); + + p.cargo("doc --examples") + // The checking/documenting lines are sometimes swapped since they run + // concurrently. + .with_stderr_data( + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/ex1/index.html and 1 other file + +"#]] + .unordered(), + ) + .run(); + + let example_doc_html_1 = p.read_file("target/doc/ex1/index.html"); + let example_doc_html_2 = p.read_file("target/doc/ex2/index.html"); + + assert!(!example_doc_html_1.contains("Library")); + assert!(!example_doc_html_1.contains("Binary")); + + assert!(!example_doc_html_2.contains("Library")); + assert!(!example_doc_html_2.contains("Binary")); + + assert!(example_doc_html_1.contains("Example1")); + assert!(example_doc_html_2.contains("Example2")); +} + +#[cargo_test] +fn doc_dash_p() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "extern crate a;") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.b] + path = "../b" + "#, + ) + .file("a/src/lib.rs", "extern crate b;") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("doc -p a") + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[DOCUMENTING] b v0.0.1 ([ROOT]/foo/b) +[CHECKING] b v0.0.1 ([ROOT]/foo/b) +[DOCUMENTING] a v0.0.1 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/a/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doc_all_exclude() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("doc --workspace --exclude baz") + .with_stderr_data(str![[r#" +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_all_exclude_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("doc --workspace --exclude '*z'") + .with_stderr_data(str![[r#" +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_same_name() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/main.rs", "fn main() {}") + .file("examples/main.rs", "fn main() {}") + .file("tests/main.rs", "fn main() {}") + .build(); + + p.cargo("doc").run(); +} + +#[cargo_test(nightly, reason = "no_core, lang_items requires nightly")] +fn doc_target() { + const TARGET: &str = "arm-unknown-linux-gnueabihf"; + + let p = project() + .file( + "src/lib.rs", + r#" + #![allow(internal_features)] + #![feature(no_core, lang_items)] + #![no_core] + + #[lang = "sized"] + trait Sized {} + + extern { + pub static A: u32; + } + "#, + ) + .build(); + + p.cargo("doc --verbose --target").arg(TARGET).run(); + assert!(p.root().join(&format!("target/{}/doc", TARGET)).is_dir()); + assert!(p + .root() + .join(&format!("target/{}/doc/foo/index.html", TARGET)) + .is_file()); +} + +#[cargo_test] +fn target_specific_not_documented() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.foo.dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "not rust") + .build(); + + p.cargo("doc").run(); +} + +#[cargo_test] +fn output_not_captured() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file( + "a/src/lib.rs", + " + /// ``` + /// ` + /// ``` + pub fn foo() {} + ", + ) + .build(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +... +[..]unknown start of token: ` +... +"#]]) + .run(); +} + +#[cargo_test] +fn target_specific_documented() { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.foo.dependencies] + a = {{ path = "a" }} + [target.{}.dependencies] + a = {{ path = "a" }} + "#, + rustc_host() + ), + ) + .file( + "src/lib.rs", + " + extern crate a; + + /// test + pub fn foo() {} + ", + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file( + "a/src/lib.rs", + " + /// test + pub fn foo() {} + ", + ) + .build(); + + p.cargo("doc").run(); +} + +#[cargo_test] +fn no_document_build_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [build-dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file( + "a/src/lib.rs", + " + /// ``` + /// ☃ + /// ``` + pub fn foo() {} + ", + ) + .build(); + + p.cargo("doc").run(); +} + +#[cargo_test] +fn doc_release() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check --release").run(); + p.cargo("doc --release -v") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..] src/lib.rs [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_multiple_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + + [dependencies.baz] + path = "baz" + "#, + ) + .file("src/lib.rs", "extern crate bar; pub fn foo() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("doc -p bar -p baz -v").run(); + + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/bar/index.html").is_file()); + assert!(p.root().join("target/doc/baz/index.html").is_file()); +} + +#[cargo_test] +fn features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + + [features] + foo = ["bar/bar"] + "#, + ) + .file("src/lib.rs", r#"#[cfg(feature = "foo")] pub fn foo() {}"#) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + bar = [] + "#, + ) + .file( + "bar/build.rs", + r#" + fn main() { + println!("cargo::rustc-cfg=bar"); + } + "#, + ) + .file( + "bar/src/lib.rs", + r#"#[cfg(feature = "bar")] pub fn bar() {}"#, + ) + .build(); + p.cargo("doc --features foo") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + assert!(p.root().join("target/doc").is_dir()); + assert!(p.root().join("target/doc/foo/fn.foo.html").is_file()); + assert!(p.root().join("target/doc/bar/fn.bar.html").is_file()); + // Check that turning the feature off will remove the files. + p.cargo("doc") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + assert!(!p.root().join("target/doc/foo/fn.foo.html").is_file()); + assert!(!p.root().join("target/doc/bar/fn.bar.html").is_file()); + // And switching back will rebuild and bring them back. + p.cargo("doc --features foo") + .with_stderr_data(str![[r#" +[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + assert!(p.root().join("target/doc/foo/fn.foo.html").is_file()); + assert!(p.root().join("target/doc/bar/fn.bar.html").is_file()); +} + +#[cargo_test] +fn rerun_when_dir_removed() { + let p = project() + .file( + "src/lib.rs", + r#" + /// dox + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("doc").run(); + assert!(p.root().join("target/doc/foo/index.html").is_file()); + + fs::remove_dir_all(p.root().join("target/doc/foo")).unwrap(); + + p.cargo("doc").run(); + assert!(p.root().join("target/doc/foo/index.html").is_file()); +} + +#[cargo_test] +fn document_only_lib() { + let p = project() + .file( + "src/lib.rs", + r#" + /// dox + pub fn foo() {} + "#, + ) + .file( + "src/bin/bar.rs", + r#" + /// ``` + /// ☃ + /// ``` + pub fn foo() {} + fn main() { foo(); } + "#, + ) + .build(); + p.cargo("doc --lib").run(); + assert!(p.root().join("target/doc/foo/index.html").is_file()); +} + +#[cargo_test] +fn plugins_no_use_target() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("doc --target=x86_64-unknown-openbsd -v").run(); +} + +#[cargo_test] +fn doc_all_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + // The order in which bar is compiled or documented is not deterministic + p.cargo("doc --workspace") + .with_stderr_data( + str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html and 1 other file + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doc_all_workspace_verbose() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + // The order in which bar is compiled or documented is not deterministic + p.cargo("doc --workspace -v") + .with_stderr_data( + str![[r#" +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustdoc [..] +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[RUNNING] `rustc [..] +[RUNNING] `rustdoc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doc_all_virtual_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + // The order in which bar and baz are documented is not guaranteed + p.cargo("doc --workspace") + .with_stderr_data( + str![[r#" +[DOCUMENTING] baz v0.1.0 ([ROOT]/foo/baz) +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html and 1 other file + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doc_virtual_manifest_all_implied() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + // The order in which bar and baz are documented is not guaranteed + p.cargo("doc") + .with_stderr_data( + str![[r#" +[GENERATED] [ROOT]/foo/target/doc/bar/index.html and 1 other file +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[DOCUMENTING] baz v0.1.0 ([ROOT]/foo/baz) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doc_virtual_manifest_one_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() { break_the_build(); }") + .build(); + + p.cargo("doc -p bar") + .with_stderr_data(str![[r#" +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_virtual_manifest_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() { break_the_build(); }") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("doc -p '*z'") + .with_stderr_data(str![[r#" +[DOCUMENTING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/baz/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_all_member_dependency_same_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + Package::new("bar", "0.1.0").publish(); + + p.cargo("doc --workspace") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[WARNING] output filename collision. +The lib target `bar` in package `bar v0.1.0` has the same output filename as the lib target `bar` in package `bar v0.1.0 ([ROOT]/foo/bar)`. +Colliding filename is: [ROOT]/foo/target/doc/bar/index.html +The targets should have unique names. +This is a known bug where multiple crates with the same name use +the same path; see . +[DOCUMENTING] bar v0.1.0 +[CHECKING] bar v0.1.0 +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn doc_workspace_open_help_message() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + // The order in which bar is compiled or documented is not deterministic + p.cargo("doc --workspace --open") + .env("BROWSER", tools::echo()) + .with_stderr_data( + str![[r#" +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo) +[DOCUMENTING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[OPENING] [ROOT]/foo/target/doc/bar/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test(nightly, reason = "-Zextern-html-root-url is unstable")] +fn doc_extern_map_local() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .file(".cargo/config.toml", "doc.extern-map.std = 'local'") + .build(); + + p.cargo("doc -v --no-deps -Zrustdoc-map --open") + .env("BROWSER", tools::echo()) + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type lib --crate-name foo src/lib.rs [..]--crate-version 0.1.0` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[OPENING] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn open_no_doc_crate() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + doc = false + "#, + ) + .file("src/lib.rs", "#[cfg(feature)] pub fn f();") + .build(); + + p.cargo("doc --open") + .env("BROWSER", "do_not_run_me") + .with_status(101) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[ERROR] cannot open specified crate's documentation: no documentation generated + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_workspace_open_different_library_and_package_names() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + name = "foolib" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("doc --open") + .env("BROWSER", tools::echo()) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[OPENING] [ROOT]/foo/target/doc/foolib/index.html + +"#]]) + .with_stdout_data(str![[r#" +[ROOT]/foo/target/doc/foolib/index.html + +"#]]) + .run(); + + p.change_file( + ".cargo/config.toml", + &format!( + r#" + [doc] + browser = ["{}", "a"] + "#, + tools::echo().display().to_string().replace('\\', "\\\\") + ), + ); + + // check that the cargo config overrides the browser env var + p.cargo("doc --open") + .env("BROWSER", "do_not_run_me") + .with_stdout_data(str![[r#" +a [ROOT]/foo/target/doc/foolib/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_workspace_open_binary() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [[bin]] + name = "foobin" + path = "src/main.rs" + "#, + ) + .file("foo/src/main.rs", "") + .build(); + + p.cargo("doc --open") + .env("BROWSER", tools::echo()) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[OPENING] [ROOT]/foo/target/doc/foobin/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_workspace_open_binary_and_library() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + name = "foolib" + [[bin]] + name = "foobin" + path = "src/main.rs" + "#, + ) + .file("foo/src/lib.rs", "") + .file("foo/src/main.rs", "") + .build(); + + p.cargo("doc --open") + .env("BROWSER", tools::echo()) + .with_stderr_data( + str![[r#" +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo/foo) +[CHECKING] foo v0.1.0 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[OPENING] [ROOT]/foo/target/doc/foolib/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doc_edition() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2018" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--edition=2018[..] +... +"#]]) + .run(); + + p.cargo("test -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--edition=2018[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn doc_target_edition() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + edition = "2018" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--edition=2018[..] +... +"#]]) + .run(); + + p.cargo("test -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--edition=2018[..] +... +"#]]) + .run(); +} + +// Tests an issue where depending on different versions of the same crate depending on `cfg`s +// caused `cargo doc` to fail. +#[cargo_test] +fn issue_5345() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(all(windows, target_arch = "x86"))'.dependencies] + bar = "0.1" + + [target.'cfg(not(all(windows, target_arch = "x86")))'.dependencies] + bar = "0.2" + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .build(); + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.2.0").publish(); + + foo.cargo("check").run(); + foo.cargo("doc").run(); +} + +#[cargo_test] +fn doc_private_items() { + let foo = project() + .file("src/lib.rs", "mod private { fn private_item() {} }") + .build(); + foo.cargo("doc --document-private-items").run(); + + assert!(foo.root().join("target/doc").is_dir()); + assert!(foo + .root() + .join("target/doc/foo/private/index.html") + .is_file()); +} + +#[cargo_test] +fn doc_private_ws() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "fn p() {}") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "fn p2() {}") + .file("b/src/bin/b-cli.rs", "fn main() {}") + .build(); + p.cargo("doc --workspace --bins --lib --document-private-items -v") + .with_stderr_data( + str![[r#" +[DOCUMENTING] b v0.0.1 ([ROOT]/foo/b) +[CHECKING] b v0.0.1 ([ROOT]/foo/b) +[DOCUMENTING] a v0.0.1 ([ROOT]/foo/a) +[RUNNING] `rustdoc [..] a/src/lib.rs [..]--document-private-items[..] +[RUNNING] `rustc [..] +[WARNING] function `p2` is never used +... +[RUNNING] `rustdoc [..] b/src/lib.rs [..]--document-private-items[..] +[WARNING] `b` (lib) generated 1 warning +[RUNNING] `rustdoc [..] b/src/bin/b-cli.rs [..]--document-private-items[..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/a/index.html +[GENERATED] [ROOT]/foo/target/doc/b/index.html +[GENERATED] [ROOT]/foo/target/doc/b_cli/index.html + +"#]] + .unordered(), + ) + .run(); +} + +const BAD_INTRA_LINK_LIB: &str = r#" +#![deny(rustdoc::broken_intra_doc_links)] + +/// [bad_link] +pub fn foo() {} +"#; + +#[cargo_test] +fn doc_cap_lints() { + let a = git::new("a", |p| { + p.file("Cargo.toml", &basic_lib_manifest("a")) + .file("src/lib.rs", BAD_INTRA_LINK_LIB) + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = {{ git = '{}' }} + "#, + a.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc") + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[UPDATING] git repository `[..]` +[DOCUMENTING] a v0.5.0 ([..]) +[CHECKING] a v0.5.0 ([..]) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); + + p.root().join("target").rm_rf(); + + p.cargo("doc -vv") + .with_stderr_data(str![[r#" +... +[WARNING] [..]`bad_link`[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn doc_message_format() { + let p = project().file("src/lib.rs", BAD_INTRA_LINK_LIB).build(); + + p.cargo("doc --message-format=json") + .with_status(101) + .with_stdout_data( + str![[r##" +[ + { + "manifest_path": "[ROOT]/foo/Cargo.toml", + "message": { + "$message_type": "diagnostic", + "level": "error", + "...": "{...}" + }, + "package_id": "path+[ROOTURL]/foo#0.0.1", + "reason": "compiler-message", + "target": "{...}" + }, + "{...}" +] +"##]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn doc_json_artifacts() { + // Checks the output of json artifact messages. + let p = project() + .file("src/lib.rs", "") + .file("src/bin/somebin.rs", "fn main() {}") + .build(); + + p.cargo("doc --message-format=json") + .with_stdout_data( + str![[r#" +[ + { + "executable": null, + "features": [], + "filenames": [ + "[ROOT]/foo/target/debug/deps/libfoo-[HASH].rmeta" + ], + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + }, + { + "executable": null, + "features": [], + "filenames": [ + "[ROOT]/foo/target/doc/foo/index.html" + ], + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + }, + { + "executable": null, + "features": [], + "filenames": [ + "[ROOT]/foo/target/doc/somebin/index.html" + ], + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "somebin", + "src_path": "[ROOT]/foo/src/bin/somebin.rs", + "test": true + } + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines() + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn short_message_format() { + let p = project().file("src/lib.rs", BAD_INTRA_LINK_LIB).build(); + p.cargo("doc --message-format=short") + .with_status(101) + .with_stderr_data(str![[r#" +... +src/lib.rs:4:6: [ERROR] [..]`bad_link`[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn doc_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [[example]] + crate-type = ["lib"] + name = "ex1" + doc = true + "#, + ) + .file("src/lib.rs", "pub fn f() {}") + .file( + "examples/ex1.rs", + r#" + use foo::f; + + /// Example + pub fn x() { f(); } + "#, + ) + .build(); + + p.cargo("doc").run(); + assert!(p + .build_dir() + .join("doc") + .join("ex1") + .join("fn.x.html") + .exists()); +} + +#[cargo_test] +fn doc_example_with_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [[example]] + crate-type = ["lib"] + name = "ex" + doc = true + + [dev-dependencies] + a = {path = "a"} + b = {path = "b"} + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + use a::fun; + + /// Example + pub fn x() { fun(); } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + + [dependencies] + b = {path = "../b"} + "#, + ) + .file("a/src/fun.rs", "pub fn fun() {}") + .file("a/src/lib.rs", "pub mod fun;") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("doc --examples").run(); + assert!(p + .build_dir() + .join("doc") + .join("ex") + .join("fn.x.html") + .exists()); +} + +#[cargo_test] +fn bin_private_items() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file( + "src/main.rs", + " + pub fn foo_pub() {} + fn foo_priv() {} + struct FooStruct; + enum FooEnum {} + trait FooTrait {} + type FooType = u32; + mod foo_mod {} + + ", + ) + .build(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!(p.root().join("target/doc/foo/fn.foo_pub.html").is_file()); + assert!(p.root().join("target/doc/foo/fn.foo_priv.html").is_file()); + assert!(p + .root() + .join("target/doc/foo/struct.FooStruct.html") + .is_file()); + assert!(p.root().join("target/doc/foo/enum.FooEnum.html").is_file()); + assert!(p + .root() + .join("target/doc/foo/trait.FooTrait.html") + .is_file()); + assert!(p.root().join("target/doc/foo/type.FooType.html").is_file()); + assert!(p.root().join("target/doc/foo/foo_mod/index.html").is_file()); +} + +#[cargo_test] +fn bin_private_items_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + "src/main.rs", + " + fn foo_priv() {} + pub fn foo_pub() {} + ", + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "bar/src/lib.rs", + " + #[allow(dead_code)] + fn bar_priv() {} + pub fn bar_pub() {} + ", + ) + .build(); + + p.cargo("doc") + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar) +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); + + assert!(p.root().join("target/doc/foo/index.html").is_file()); + assert!(p.root().join("target/doc/foo/fn.foo_pub.html").is_file()); + assert!(p.root().join("target/doc/foo/fn.foo_priv.html").is_file()); + + assert!(p.root().join("target/doc/bar/index.html").is_file()); + assert!(p.root().join("target/doc/bar/fn.bar_pub.html").is_file()); + assert!(!p.root().join("target/doc/bar/fn.bar_priv.html").exists()); +} + +#[cargo_test] +fn crate_versions() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.2.4" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc -v") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v1.2.4 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type lib --crate-name foo src/lib.rs [..]--crate-version 1.2.4` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + 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("1.2.4")); +} + +#[cargo_test] +fn crate_versions_flag_is_overridden() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.2.4" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + let output_documentation = || { + let output_path = p.root().join("target/doc/foo/index.html"); + fs::read_to_string(&output_path).unwrap() + }; + let asserts = |html: String| { + assert!(!html.contains("1.2.4")); + assert!(html.contains("2.0.3")); + }; + + p.cargo("doc") + .env("RUSTDOCFLAGS", "--crate-version 2.0.3") + .run(); + asserts(output_documentation()); + + p.build_dir().rm_rf(); + + p.cargo("rustdoc -- --crate-version 2.0.3").run(); + asserts(output_documentation()); +} + +#[cargo_test] +fn doc_test_in_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [ + "crate-a", + "crate-b", + ] + "#, + ) + .file( + "crate-a/Cargo.toml", + r#" + [package] + name = "crate-a" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "crate-a/src/lib.rs", + "\ + //! ``` + //! assert_eq!(1, 1); + //! ``` + ", + ) + .file( + "crate-b/Cargo.toml", + r#" + [package] + name = "crate-b" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "crate-b/src/lib.rs", + "\ + //! ``` + //! assert_eq!(1, 1); + //! ``` + ", + ) + .build(); + p.cargo("test --doc -vv") + .with_stderr_data(str![[r#" +... +[DOCTEST] crate_a +... +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test crate-a/src/lib.rs - (line 1) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test crate-b/src/lib.rs - (line 1) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +/// This is a test for . +/// The `file!()` macro inside of an `include!()` should output +/// workspace-relative paths, just like it does in other cases. +#[cargo_test] +fn doc_test_include_file() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [ + "child", + ] + [package] + name = "root" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "src/lib.rs", + r#" + /// ``` + /// assert_eq!("src/lib.rs", file!().replace("\\", "/")) + /// ``` + pub mod included { + include!(concat!("../", file!(), ".included.rs")); + } + "#, + ) + .file( + "src/lib.rs.included.rs", + r#" + /// ``` + /// assert_eq!(1, 1) + /// ``` + pub fn foo() {} + "#, + ) + .file( + "child/Cargo.toml", + r#" + [package] + name = "child" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "child/src/lib.rs", + r#" + /// ``` + /// assert_eq!("child/src/lib.rs", file!().replace("\\", "/")) + /// ``` + pub mod included { + include!(concat!("../../", file!(), ".included.rs")); + } + "#, + ) + .file( + "child/src/lib.rs.included.rs", + r#" + /// ``` + /// assert_eq!(1, 1) + /// ``` + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("test --workspace --doc -vv -- --test-threads=1") + .with_stderr_data(str![[r#" +... +[DOCTEST] child +... +[DOCTEST] root +... +"#]]) + .with_stdout_data(str![[r#" + +running 2 tests +test child/src/../../child/src/lib.rs.included.rs - included::foo (line 2) ... ok +test child/src/lib.rs - included (line 2) ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 2 tests +test src/../src/lib.rs.included.rs - included::foo (line 2) ... ok +test src/lib.rs - included (line 2) ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_fingerprint_is_versioning_consistent() { + // Random rustc verbose version + let old_rustc_verbose_version = format!( + "\ +rustc 1.41.1 (f3e1a954d 2020-02-24) +binary: rustc +commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196 +commit-date: 2020-02-24 +host: {} +release: 1.41.1 +LLVM version: 9.0 +", + rustc_host() + ); + + // Create the dummy project. + let dummy_project = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.2.4" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "//! These are the docs!") + .build(); + + dummy_project.cargo("doc").run(); + + let fingerprint: RustDocFingerprint = + serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json")) + .expect("JSON Serde fail"); + + // Check that the fingerprint contains the actual rustc version + // which has been used to compile the docs. + let output = std::process::Command::new("rustc") + .arg("-vV") + .output() + .expect("Failed to get actual rustc verbose version"); + assert_eq!( + fingerprint.rustc_vv, + (String::from_utf8_lossy(&output.stdout).as_ref()) + ); + + // As the test shows above. Now we have generated the `doc/` folder and inside + // the rustdoc fingerprint file is located with the correct rustc version. + // So we will remove it and create a new fingerprint with an old rustc version + // inside it. We will also place a bogus file inside of the `doc/` folder to ensure + // it gets removed as we expect on the next doc compilation. + dummy_project.change_file( + "target/.rustdoc_fingerprint.json", + &old_rustc_verbose_version, + ); + + fs::write( + dummy_project.build_dir().join("doc/bogus_file"), + String::from("This is a bogus file and should be removed!"), + ) + .expect("Error writing test bogus file"); + + // Now if we trigger another compilation, since the fingerprint contains an old version + // of rustc, cargo should remove the entire `/doc` folder (including the fingerprint) + // and generating another one with the actual version. + // It should also remove the bogus file we created above. + dummy_project.cargo("doc").run(); + + assert!(!dummy_project.build_dir().join("doc/bogus_file").exists()); + + let fingerprint: RustDocFingerprint = + serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json")) + .expect("JSON Serde fail"); + + // Check that the fingerprint contains the actual rustc version + // which has been used to compile the docs. + assert_eq!( + fingerprint.rustc_vv, + (String::from_utf8_lossy(&output.stdout).as_ref()) + ); +} + +#[cargo_test] +fn doc_fingerprint_respects_target_paths() { + // Random rustc verbose version + let old_rustc_verbose_version = format!( + "\ +rustc 1.41.1 (f3e1a954d 2020-02-24) +binary: rustc +commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196 +commit-date: 2020-02-24 +host: {} +release: 1.41.1 +LLVM version: 9.0 +", + rustc_host() + ); + + // Create the dummy project. + let dummy_project = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.2.4" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "//! These are the docs!") + .build(); + + dummy_project.cargo("doc --target").arg(rustc_host()).run(); + + let fingerprint: RustDocFingerprint = + serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json")) + .expect("JSON Serde fail"); + + // Check that the fingerprint contains the actual rustc version + // which has been used to compile the docs. + let output = std::process::Command::new("rustc") + .arg("-vV") + .output() + .expect("Failed to get actual rustc verbose version"); + assert_eq!( + fingerprint.rustc_vv, + (String::from_utf8_lossy(&output.stdout).as_ref()) + ); + + // As the test shows above. Now we have generated the `doc/` folder and inside + // the rustdoc fingerprint file is located with the correct rustc version. + // So we will remove it and create a new fingerprint with an old rustc version + // inside it. We will also place a bogus file inside of the `doc/` folder to ensure + // it gets removed as we expect on the next doc compilation. + dummy_project.change_file( + "target/.rustdoc_fingerprint.json", + &old_rustc_verbose_version, + ); + + fs::write( + dummy_project + .build_dir() + .join(rustc_host()) + .join("doc/bogus_file"), + String::from("This is a bogus file and should be removed!"), + ) + .expect("Error writing test bogus file"); + + // Now if we trigger another compilation, since the fingerprint contains an old version + // of rustc, cargo should remove the entire `/doc` folder (including the fingerprint) + // and generating another one with the actual version. + // It should also remove the bogus file we created above. + dummy_project.cargo("doc --target").arg(rustc_host()).run(); + + assert!(!dummy_project + .build_dir() + .join(rustc_host()) + .join("doc/bogus_file") + .exists()); + + let fingerprint: RustDocFingerprint = + serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json")) + .expect("JSON Serde fail"); + + // Check that the fingerprint contains the actual rustc version + // which has been used to compile the docs. + assert_eq!( + fingerprint.rustc_vv, + (String::from_utf8_lossy(&output.stdout).as_ref()) + ); +} + +#[cargo_test] +fn doc_fingerprint_unusual_behavior() { + // Checks for some unusual circumstances with clearing the doc directory. + if !symlink_supported() { + return; + } + let p = project().file("src/lib.rs", "").build(); + p.build_dir().mkdir_p(); + let real_doc = p.root().join("doc"); + real_doc.mkdir_p(); + let build_doc = p.build_dir().join("doc"); + p.symlink(&real_doc, &build_doc); + fs::write(real_doc.join("somefile"), "test").unwrap(); + fs::write(real_doc.join(".hidden"), "test").unwrap(); + p.cargo("doc").run(); + // Make sure for the first run, it does not delete any files and does not + // break the symlink. + assert!(build_doc.join("somefile").exists()); + assert!(real_doc.join("somefile").exists()); + assert!(real_doc.join(".hidden").exists()); + assert!(real_doc.join("foo/index.html").exists()); + // Pretend that the last build was generated by an older version. + p.change_file( + "target/.rustdoc_fingerprint.json", + "{\"rustc_vv\": \"I am old\"}", + ); + // Change file to trigger a new build. + p.change_file("src/lib.rs", "// changed"); + p.cargo("doc") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + // This will delete somefile, but not .hidden. + assert!(!real_doc.join("somefile").exists()); + assert!(real_doc.join(".hidden").exists()); + assert!(real_doc.join("foo/index.html").exists()); + // And also check the -Z flag behavior. + p.change_file( + "target/.rustdoc_fingerprint.json", + "{\"rustc_vv\": \"I am old\"}", + ); + // Change file to trigger a new build. + p.change_file("src/lib.rs", "// changed2"); + fs::write(real_doc.join("somefile"), "test").unwrap(); + p.cargo("doc -Z skip-rustdoc-fingerprint") + .masquerade_as_nightly_cargo(&["skip-rustdoc-fingerprint"]) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + // Should not have deleted anything. + assert!(build_doc.join("somefile").exists()); + assert!(real_doc.join("somefile").exists()); +} + +#[cargo_test] +fn lib_before_bin() { + // Checks that the library is documented before the binary. + // Previously they were built concurrently, which can cause issues + // if the bin has intra-doc links to the lib. + let p = project() + .file( + "src/lib.rs", + r#" + /// Hi + pub fn abc() {} + "#, + ) + .file( + "src/bin/somebin.rs", + r#" + //! See [`foo::abc`] + fn main() {} + "#, + ) + .build(); + + // Run check first. This just helps ensure that the test clearly shows the + // order of the rustdoc commands. + p.cargo("check").run(); + + // The order of output here should be deterministic. + p.cargo("doc -v") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type lib --crate-name foo src/lib.rs [..] +[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name somebin src/bin/somebin.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html +[GENERATED] [ROOT]/foo/target/doc/somebin/index.html + +"#]]) + .run(); + + // And the link should exist. + let bin_html = p.read_file("target/doc/somebin/index.html"); + assert!(bin_html.contains("../foo/fn.abc.html")); +} + +#[cargo_test] +fn doc_lib_false() { + // doc = false for a library + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + doc = false + + [dependencies] + bar = {path = "bar"} + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("src/bin/some-bin.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [lib] + doc = false + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/some_bin/index.html + +"#]]) + .run(); + + assert!(!p.build_dir().join("doc/foo").exists()); + assert!(!p.build_dir().join("doc/bar").exists()); + assert!(p.build_dir().join("doc/some_bin").exists()); +} + +#[cargo_test] +fn doc_lib_false_dep() { + // doc = false for a dependency + // Ensures that the rmeta gets produced + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [lib] + doc = false + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("doc") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + assert!(p.build_dir().join("doc/foo").exists()); + assert!(!p.build_dir().join("doc/bar").exists()); +} + +#[cargo_test] +fn link_to_private_item() { + let main = r#" + //! [bar] + #[allow(dead_code)] + fn bar() {} + "#; + let p = project().file("src/lib.rs", main).build(); + p.cargo("doc") + .with_stderr_data(str![[r#" +... +[..]documentation for `foo` links to private item `bar` +... +"#]]) + .run(); + // Check that binaries don't emit a private_intra_doc_links warning. + fs::rename(p.root().join("src/lib.rs"), p.root().join("src/main.rs")).unwrap(); + p.cargo("doc") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_failure_hides_command_line_by_default() { + let p = project().file("src/lib.rs", "invalid rust code").build(); + + // `cargo doc` doesn't print the full command line on failures by default + p.cargo("doc") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[ERROR] expected one of `!` or `::`, found `rust` + --> src/lib.rs:1:9 + | +1 | invalid rust code + | ^^^^ expected one of `!` or `::` + +[ERROR] could not document `foo` + +"#]]) + .with_status(101) + .run(); + + // ... but it still does so if requested with `--verbose`. + p.cargo("doc --verbose") + .with_stderr_data(str![[r#" +... +Caused by: + process didn't exit successfully[..]rustdoc[..] + +"#]]) + .with_status(101) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/docscrape.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/docscrape.rs new file mode 100644 index 000000000..eb9ad9f70 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/docscrape.rs @@ -0,0 +1,770 @@ +//! Tests for the `cargo doc` command with `-Zrustdoc-scrape-examples`. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn basic() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("examples/ex.rs", "fn main() { foo::foo(); }") + .file("src/lib.rs", "pub fn foo() {}\npub fn bar() { foo(); }") + .build(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + p.cargo("doc -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + let doc_html = p.read_file("target/doc/foo/fn.foo.html"); + assert!(doc_html.contains("Examples found in repository")); + assert!(!doc_html.contains("More examples")); + + // Ensure that the reverse-dependency has its sources generated + assert!(p.build_dir().join("doc/src/ex/ex.rs.html").exists()); +} + +// This test ensures that even if there is no `[workspace]` in the top-level `Cargo.toml` file, the +// dependencies will get their examples scraped and that they appear in the generated documentation. +#[cargo_test(nightly, reason = "-Zrustdoc-scrape-examples is unstable")] +fn scrape_examples_for_non_workspace_reexports() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + authors = [] + + [dependencies] + a = { path = "crates/a" } + "#, + ) + .file("src/lib.rs", "pub use a::*;") + // Example + .file( + "examples/one.rs", + r#"use foo::*; +fn main() { + let foo = Foo::new("yes".into()); + foo.maybe(); +}"#, + ) + // `a` crate + .file( + "crates/a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file( + "crates/a/src/lib.rs", + r#" +#[derive(Debug)] +pub struct Foo { + foo: String, + yes: bool, +} + +impl Foo { + pub fn new(foo: String) -> Self { + Self { foo, yes: true } + } + + pub fn maybe(&self) { + if self.yes { + println!("{}", self.foo) + } + } +}"#, + ) + .build(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples --no-deps") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.0.1 ([ROOT]/foo/crates/a) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); + + let doc_html = p.read_file("target/doc/foo/struct.Foo.html"); + assert!(doc_html.contains("Examples found in repository")); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn avoid_build_script_cycle() { + let p = project() + // package with build dependency + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + links = "foo" + + [workspace] + members = ["bar"] + + [build-dependencies] + bar = {path = "bar"} + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main(){}") + // dependency + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + links = "bar" + "#, + ) + .file("bar/src/lib.rs", "") + .file("bar/build.rs", "fn main(){}") + .build(); + + p.cargo("doc --workspace -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn complex_reverse_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies] + a = {path = "a", features = ["feature"]} + b = {path = "b"} + + [workspace] + members = ["b"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "fn main() {}") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + + [dependencies] + b = {path = "../b"} + + [features] + feature = [] + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("doc --workspace --examples -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn crate_with_dash() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "da-sh" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file("examples/a.rs", "fn main() { da_sh::foo(); }") + .build(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); + + let doc_html = p.read_file("target/doc/da_sh/fn.foo.html"); + assert!(doc_html.contains("Examples found in repository")); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn configure_target() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + doc-scrape-examples = true + + [[bin]] + name = "a_bin" + doc-scrape-examples = true + + [[example]] + name = "a" + doc-scrape-examples = false + "#, + ) + .file( + "src/lib.rs", + "pub fn foo() {} fn lib_must_appear() { foo(); }", + ) + .file( + "examples/a.rs", + "fn example_must_not_appear() { foo::foo(); }", + ) + .file( + "src/bin/a_bin.rs", + "fn bin_must_appear() { foo::foo(); } fn main(){}", + ) + .build(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); + + let doc_html = p.read_file("target/doc/foo/fn.foo.html"); + assert!(doc_html.contains("lib_must_appear")); + assert!(doc_html.contains("bin_must_appear")); + assert!(!doc_html.contains("example_must_not_appear")); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn configure_profile_issue_10500() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.dev] + panic = "abort" + "#, + ) + .file("examples/ex.rs", "fn main() { foo::foo(); }") + .file("src/lib.rs", "pub fn foo() {}\npub fn bar() { foo(); }") + .build(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); + + let doc_html = p.read_file("target/doc/foo/fn.foo.html"); + assert!(doc_html.contains("Examples found in repository")); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn issue_10545() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + resolver = "2" + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + authors = [] + edition = "2021" + + [features] + default = ["foo"] + foo = [] + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + authors = [] + edition = "2021" + + [lib] + proc-macro = true + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("doc --workspace -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn cache() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("examples/ex.rs", "fn main() { foo::foo(); }") + .file("src/lib.rs", "pub fn foo() {}\npub fn bar() { foo(); }") + .build(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn no_fail_bad_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "pub fn foo() { CRASH_THE_BUILD() }") + .file("examples/ex.rs", "fn main() { foo::foo(); }") + .file("examples/ex2.rs", "fn main() { foo::foo(); }") + .build(); + + p.cargo("doc -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[WARNING] failed to check lib in package `foo` as a prerequisite for scraping examples from: example "ex", example "ex2" + Try running with `--verbose` to see the error message. + If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml +[WARNING] `foo` (lib) generated 1 warning +[WARNING] failed to scan example "ex" in package `foo` for example code usage + Try running with `--verbose` to see the error message. + If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml +[WARNING] `foo` (example "ex") generated 1 warning +[WARNING] failed to scan example "ex2" in package `foo` for example code usage + Try running with `--verbose` to see the error message. + If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml +[WARNING] `foo` (example "ex2") generated 1 warning +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]].unordered()) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn fail_bad_build_script() { + // See rust-lang/cargo#11623 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() { panic!(\"You shall not pass\")}") + .file("examples/ex.rs", "fn main() {}") + .build(); + + // `cargo doc` fails + p.cargo("doc") + .with_status(101) + .with_stderr_data(str![[r#" +... +[..]You shall not pass[..] +... +"#]]) + .run(); + + // scrape examples should fail whenever `cargo doc` fails. + p.cargo("doc -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_status(101) + .with_stderr_data(str![[r#" +... +[..]You shall not pass[..] +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn no_fail_bad_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("examples/ex1.rs", "DOES NOT COMPILE") + .file("examples/ex2.rs", "fn main() { foo::foo(); }") + .file("src/lib.rs", "pub fn foo(){}") + .build(); + + p.cargo("doc -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[WARNING] failed to scan example "ex1" in package `foo` for example code usage + Try running with `--verbose` to see the error message. + If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in Cargo.toml +[WARNING] `foo` (example "ex1") generated 1 warning +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + p.cargo("clean").run(); + + p.cargo("doc -v -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data( + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo[..] +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc[..] --crate-name ex1[..] +[RUNNING] `rustdoc[..] --crate-name ex2[..] +[RUNNING] `rustdoc[..] --crate-name foo[..] +[ERROR] expected one of `!` or `::`, found `NOT` + --> examples/ex1.rs:1:6 + | +1 | DOES NOT COMPILE + | ^^^ expected one of `!` or `::` + +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); + + let doc_html = p.read_file("target/doc/foo/fn.foo.html"); + assert!(doc_html.contains("Examples found in repository")); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn no_scrape_with_dev_deps() { + // Tests that a crate with dev-dependencies does not have its examples + // scraped unless explicitly prompted to check them. See + // `UnitGenerator::create_docscrape_proposals` for details on why. + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "fn main() { a::f(); }") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("a/src/lib.rs", "pub fn f() {}") + .build(); + + // If --examples is not provided, then the example is not scanned, and a warning + // should be raised. + p.cargo("doc -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[WARNING] Rustdoc did not scrape the following examples because they require dev-dependencies: ex + If you want Rustdoc to scrape these examples, then add `doc-scrape-examples = true` + to the [[example]] target configuration of at least one example. +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + // If --examples is provided, then the example is scanned. + p.cargo("doc --examples -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data( + str![[r#" +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] a v0.0.1 ([ROOT]/foo/a) +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/ex/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn use_dev_deps_if_explicitly_enabled() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex" + doc-scrape-examples = true + + [dev-dependencies] + a = {path = "a"} + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "fn main() { a::f(); }") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("a/src/lib.rs", "pub fn f() {}") + .build(); + + // If --examples is not provided, then the example is never scanned. + p.cargo("doc -Zunstable-options -Z rustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[SCRAPING] foo v0.0.1 ([ROOT]/foo) +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn only_scrape_documented_targets() { + // package bar has doc = false and should not be eligible for documtation. + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + doc = false + + [workspace] + members = ["foo"] + + [dependencies] + foo = {{ path = "foo" }} + "# + ), + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "pub fn main() { foo::foo(); }") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("foo/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("doc --workspace -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); + + let doc_html = p.read_file("target/doc/foo/fn.foo.html"); + let example_found = doc_html.contains("Examples found in repository"); + assert!(!example_found); +} + +#[cargo_test(nightly, reason = "rustdoc scrape examples flags are unstable")] +fn issue_11496() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "repro" + version = "0.1.0" + edition = "2021" + + [lib] + proc-macro = true + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "fn main(){}") + .build(); + + p.cargo("doc -Zunstable-options -Zrustdoc-scrape-examples") + .masquerade_as_nightly_cargo(&["rustdoc-scrape-examples"]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/edition.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/edition.rs new file mode 100644 index 000000000..2c6ea53b0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/edition.rs @@ -0,0 +1,196 @@ +//! Tests for edition setting. + +use cargo::core::Edition; +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_lib_manifest, project, str}; + +#[cargo_test] +fn edition_works_for_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = '2018' + + [build-dependencies] + a = { path = 'a' } + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + a::foo(); + } + "#, + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("check -v").run(); +} + +#[cargo_test] +fn edition_unstable_gated() { + // During the period where a new edition is coming up, but not yet stable, + // this test will verify that it cannot be used on stable. If there is no + // next edition, it does nothing. + let next = match Edition::LATEST_UNSTABLE { + Some(next) => next, + None => { + eprintln!("Next edition is currently not available, skipping test."); + return; + } + }; + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "{}" + "#, + next + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(format!( + "\ +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `edition{next}` is required + + The package requires the Cargo feature called `edition{next}`, but that feature is not stabilized in this version of Cargo (1.[..]). + Consider trying a newer version of Cargo (this may require the nightly release). + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#edition-{next} for more information about the status of this feature. +")) + .run(); +} + +#[cargo_test(nightly, reason = "fundamentally always nightly")] +fn edition_unstable() { + // During the period where a new edition is coming up, but not yet stable, + // this test will verify that it can be used with `cargo-features`. If + // there is no next edition, it does nothing. + let next = match Edition::LATEST_UNSTABLE { + Some(next) => next, + None => { + eprintln!("Next edition is currently not available, skipping test."); + return; + } + }; + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + cargo-features = ["edition{next}"] + + [package] + name = "foo" + version = "0.1.0" + edition = "{next}" + "#, + next = next + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["always_nightly"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unset_edition_with_unset_rust_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[WARNING] no edition set: defaulting to the 2015 edition while the latest is [..] +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] --edition=2015 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unset_edition_works_with_no_newer_compatible_edition() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + rust-version = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] --edition=2015 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unset_edition_works_on_old_msrv() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + rust-version = "1.50" # contains 2018 edition + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[WARNING] no edition set: defaulting to the 2015 edition while 2018 is compatible with `rust-version` +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] --edition=2015 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/error.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/error.rs new file mode 100644 index 000000000..2d64c73e7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/error.rs @@ -0,0 +1,21 @@ +//! General error tests that don't belong anywhere else. + +use cargo_test_support::cargo_process; +use cargo_test_support::prelude::*; + +#[cargo_test] +fn internal_error() { + cargo_process("init") + .env("__CARGO_TEST_INTERNAL_ERROR", "1") + .with_status(101) + .with_stderr_data(format!( + "\ +[ERROR] internal error test +[NOTE] this is an unexpected cargo internal error +[NOTE] we would appreciate a bug report: https://github.com/rust-lang/cargo/issues/ +[NOTE] cargo {} +", + cargo::version() + )) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/feature_unification.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/feature_unification.rs new file mode 100644 index 000000000..59a9dd17e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/feature_unification.rs @@ -0,0 +1,205 @@ +//! Tests for workspace feature unification. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, cargo_process, project, str}; + +#[cargo_test] +fn workspace_feature_unification() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [resolver] + feature-unification = "workspace" + "#, + ) + .file( + "Cargo.toml", + r#" + [workspace] + resolver = "2" + members = ["common", "a", "b"] + "#, + ) + .file( + "common/Cargo.toml", + r#" + [package] + name = "common" + version = "0.1.0" + edition = "2021" + + [features] + a = [] + b = [] + "#, + ) + .file( + "common/src/lib.rs", + r#" + #[cfg(not(all(feature = "a", feature = "b")))] + compile_error!("features were not unified"); + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2021" + + [dependencies] + common = { path = "../common", features = ["a"] } + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2021" + + [dependencies] + common = { path = "../common", features = ["b"] } + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check -p common") + .arg("-Zfeature-unification") + .masquerade_as_nightly_cargo(&["feature-unification"]) + .with_stderr_data(str![[r#" +[CHECKING] common v0.1.0 ([ROOT]/foo/common) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -p a") + .arg("-Zfeature-unification") + .masquerade_as_nightly_cargo(&["feature-unification"]) + .with_stderr_data(str![[r#" +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -p b") + .arg("-Zfeature-unification") + .masquerade_as_nightly_cargo(&["feature-unification"]) + .with_stderr_data(str![[r#" +[CHECKING] b v0.1.0 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .arg("-Zfeature-unification") + .masquerade_as_nightly_cargo(&["feature-unification"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_install_ignores_config() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2021" + + [dependencies] + common = { path = "common", features = ["a"] } + + [workspace] + members = ["common", "b"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "common/Cargo.toml", + r#" + [package] + name = "common" + version = "0.1.0" + edition = "2021" + + [features] + a = [] + b = [] + "#, + ) + .file( + "common/src/lib.rs", + r#" + #[cfg(all(feature = "a", feature = "b"))] + compile_error!("features should not be unified"); + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2021" + + [dependencies] + common = { path = "../common", features = ["b"] } + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + cargo_process("install --path") + .arg(p.root()) + .arg("-Zfeature-unification") + .masquerade_as_nightly_cargo(&["feature-unification"]) + .env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace") + .with_stderr_data(str![[r#" +[INSTALLING] a v0.1.0 ([ROOT]/foo) +[COMPILING] common v0.1.0 ([ROOT]/foo/common) +[COMPILING] a v0.1.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/a[EXE] +[INSTALLED] package `a v0.1.0 ([ROOT]/foo)` (executable `a[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn unstable_config_on_stable() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + resolver = "2" + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .env("CARGO_RESOLVER_FEATURE_UNIFICATION", "workspace") + .with_stderr_data(str![[r#" +[WARNING] ignoring `resolver.feature-unification` without `-Zfeature-unification` +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features.rs new file mode 100644 index 000000000..94a69cc6e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features.rs @@ -0,0 +1,2284 @@ +//! Tests for `[features]` table. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, project}; + +#[cargo_test] +fn invalid1() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + bar = ["baz"] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `bar` includes `baz` which is neither a dependency nor another feature + +"#]]) + .run(); +} + +#[cargo_test] +fn empty_feature_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + "" = [] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] feature name cannot be empty + --> Cargo.toml:9:17 + | +9 | "" = [] + | ^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn same_name() { + // Feature with the same name as a dependency. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + bar = ["baz"] + baz = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("tree -f") + .arg("{p} [{f}]") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version + +"#]]) + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) [] +└── bar v1.0.0 ([ROOT]/foo/bar) [] + +"#]]) + .run(); + + p.cargo("tree --features bar -f") + .arg("{p} [{f}]") + .with_stderr_data("") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) [bar,baz] +└── bar v1.0.0 ([ROOT]/foo/bar) [] + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid3() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + bar = ["baz"] + + [dependencies.baz] + path = "foo" + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `bar` includes `baz`, but `baz` is not an optional dependency + A non-optional dependency of the same name is defined; consider adding `optional = true` to its definition. + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid4() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + features = ["bar"] + "#, + ) + .file("src/main.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to select a version for `bar`. + ... required by package `foo v0.0.1 ([ROOT]/foo)` +versions that meet the requirements `*` are: 0.0.1 + +the package `foo` depends on `bar`, with features: `bar` but `bar` does not have these features. + + +failed to select a version for `bar` which could resolve this conflict + +"#]]) + .run(); + + p.change_file("Cargo.toml", &basic_manifest("foo", "0.0.1")); + + p.cargo("check --features test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Package `foo v0.0.1 ([ROOT]/foo)` does not have the feature `test` + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid5() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies.bar] + path = "bar" + optional = true + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dev-dependencies are not allowed to be optional: `bar` + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid6() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + foo = ["bar/baz"] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check --features foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] feature `foo` includes `bar/baz`, but `bar` is not a dependency + --> Cargo.toml:9:23 + | +9 | foo = ["bar/baz"] + | ^^^^^^^^^^^ + | +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid7() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + foo = ["bar/baz"] + bar = [] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check --features foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] feature `foo` includes `bar/baz`, but `bar` is not a dependency + --> Cargo.toml:9:23 + | +9 | foo = ["bar/baz"] + | ^^^^^^^^^^^ + | +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid8() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + features = ["foo/bar"] + "#, + ) + .file("src/main.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check --features foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `foo/bar` in dependency `bar` is not allowed to contain slashes + If you want to enable features [..] + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid9() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check --features bar") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] Package `foo v0.0.1 ([ROOT]/foo)` does not have feature `bar`. It has a required dependency with that name, but only optional dependencies can be used as features. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn invalid10() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + features = ["baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.baz] + path = "baz" + "#, + ) + .file("bar/src/lib.rs", "") + .file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("bar/baz/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[ERROR] failed to select a version for `bar`. + ... required by package `foo v0.0.1 ([ROOT]/foo)` +versions that meet the requirements `*` are: 0.0.1 + +the package `foo` depends on `bar`, with features: `baz` but `bar` does not have these features. + It has a required dependency with that name, but only optional dependencies can be used as features. + + +failed to select a version for `bar` which could resolve this conflict + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn no_transitive_dep_feature_requirement() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.derived] + path = "derived" + + [features] + default = ["derived/bar/qux"] + "#, + ) + .file( + "src/main.rs", + r#" + extern crate derived; + fn main() { derived::test(); } + "#, + ) + .file( + "derived/Cargo.toml", + r#" + [package] + name = "derived" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file("derived/src/lib.rs", "extern crate bar; pub use bar::test;") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + qux = [] + "#, + ) + .file( + "bar/src/lib.rs", + r#" + #[cfg(feature = "qux")] + pub fn test() { print!("test"); } + "#, + ) + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + multiple slashes in feature `derived/bar/qux` (included by feature `default`) are not allowed + +"#]]) + .run(); +} + +#[cargo_test] +fn no_feature_doesnt_build() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + optional = true + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(feature = "bar")] + extern crate bar; + #[cfg(feature = "bar")] + fn main() { bar::bar(); println!("bar") } + #[cfg(not(feature = "bar"))] + fn main() {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.process(&p.bin("foo")).with_stdout_data("").run(); + + let expected = if cfg!(target_os = "windows") && cfg!(target_env = "msvc") { + str![[r#" +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..]` +[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + } else { + str![[r#" +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + }; + p.cargo("build --features bar -v") + .with_stderr_data(expected) + .run(); + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +bar + +"#]]) + .run(); +} + +#[cargo_test] +fn default_feature_pulled_in() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["bar"] + + [dependencies.bar] + path = "bar" + optional = true + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(feature = "bar")] + extern crate bar; + #[cfg(feature = "bar")] + fn main() { bar::bar(); println!("bar") } + #[cfg(not(feature = "bar"))] + fn main() {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +bar + +"#]]) + .run(); + + let expected = if cfg!(target_os = "windows") && cfg!(target_env = "msvc") { + str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + } else { + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + }; + p.cargo("build --no-default-features -v") + .with_stderr_data(expected) + .run(); + p.process(&p.bin("foo")).with_stdout_data("").run(); +} + +#[cargo_test] +fn cyclic_feature() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["default"] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cyclic feature dependency: feature `default` depends on itself + +"#]]) + .run(); +} + +#[cargo_test] +fn cyclic_feature2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + foo = ["bar"] + bar = ["foo"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn groups_on_groups_on_groups() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["f1"] + f1 = ["f2", "bar"] + f2 = ["f3", "f4"] + f3 = ["f5", "f6", "baz"] + f4 = ["f5", "f7"] + f5 = ["f6"] + f6 = ["f7"] + f7 = ["bar"] + + [dependencies.bar] + path = "bar" + optional = true + + [dependencies.baz] + path = "baz" + optional = true + "#, + ) + .file( + "src/main.rs", + r#" + #[allow(unused_extern_crates)] + extern crate bar; + #[allow(unused_extern_crates)] + extern crate baz; + fn main() {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[CHECKING] baz v0.0.1 ([ROOT]/foo/baz) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn many_cli_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + optional = true + + [dependencies.baz] + path = "baz" + optional = true + "#, + ) + .file( + "src/main.rs", + r#" + #[allow(unused_extern_crates)] + extern crate bar; + #[allow(unused_extern_crates)] + extern crate baz; + fn main() {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check --features") + .arg("bar baz") + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[CHECKING] baz v0.0.1 ([ROOT]/foo/baz) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn union_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "d1" + features = ["f1"] + [dependencies.d2] + path = "d2" + features = ["f2"] + "#, + ) + .file( + "src/main.rs", + r#" + #[allow(unused_extern_crates)] + extern crate d1; + extern crate d2; + fn main() { + d2::f1(); + d2::f2(); + } + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + f1 = ["d2"] + + [dependencies.d2] + path = "../d2" + features = ["f1"] + optional = true + "#, + ) + .file("d1/src/lib.rs", "") + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + f1 = [] + f2 = [] + "#, + ) + .file( + "d2/src/lib.rs", + r#" + #[cfg(feature = "f1")] pub fn f1() {} + #[cfg(feature = "f2")] pub fn f2() {} + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] d2 v0.0.1 ([ROOT]/foo/d2) +[CHECKING] d1 v0.0.1 ([ROOT]/foo/d1) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn many_features_no_rebuilds() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies.a] + path = "a" + features = ["fall"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + ftest = [] + ftest2 = [] + fall = ["ftest", "ftest2"] + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[CHECKING] b v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.root().move_into_the_past(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[FRESH] a v0.1.0 ([ROOT]/foo/a) +[FRESH] b v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +// Tests that all cmd lines work with `--features ""` +#[cargo_test] +fn empty_features() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("check --features").arg("").run(); +} + +// Tests that all cmd lines work with `--features ""` +#[cargo_test] +fn transitive_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + foo = ["bar/baz"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::baz(); }") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + baz = [] + "#, + ) + .file( + "bar/src/lib.rs", + r#"#[cfg(feature = "baz")] pub fn baz() {}"#, + ) + .build(); + + p.cargo("check --features foo").run(); +} + +#[cargo_test] +fn everything_in_the_lockfile() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + f1 = ["d1/f1"] + f2 = ["d2"] + + [dependencies.d1] + path = "d1" + [dependencies.d2] + path = "d2" + optional = true + [dependencies.d3] + path = "d3" + optional = true + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + f1 = [] + "#, + ) + .file("d1/src/lib.rs", "") + .file("d2/Cargo.toml", &basic_manifest("d2", "0.0.2")) + .file("d2/src/lib.rs", "") + .file( + "d3/Cargo.toml", + r#" + [package] + name = "d3" + version = "0.0.3" + edition = "2015" + authors = [] + + [features] + f3 = [] + "#, + ) + .file("d3/src/lib.rs", "") + .build(); + + p.cargo("fetch").run(); + let lockfile = p.read_lockfile(); + assert!( + lockfile.contains(r#"name = "d1""#), + "d1 not found\n{}", + lockfile + ); + assert!( + lockfile.contains(r#"name = "d2""#), + "d2 not found\n{}", + lockfile + ); + assert!( + lockfile.contains(r#"name = "d3""#), + "d3 not found\n{}", + lockfile + ); +} + +#[cargo_test] +fn no_rebuild_when_frobbing_default_feature() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + b = { path = "b" } + "#, + ) + .file("src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "../a", features = ["f1"], default-features = false } + "#, + ) + .file("b/src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["f1"] + f1 = [] + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unions_work_with_no_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + b = { path = "b" } + "#, + ) + .file("src/lib.rs", "extern crate a; pub fn foo() { a::a(); }") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "../a", features = [], default-features = false } + "#, + ) + .file("b/src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["f1"] + f1 = [] + "#, + ) + .file("a/src/lib.rs", r#"#[cfg(feature = "f1")] pub fn a() {}"#) + .build(); + + p.cargo("check").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn optional_and_dev_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = "foo", optional = true } + [dev-dependencies] + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] test v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn activating_feature_activates_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = "foo", optional = true } + + [features] + a = ["foo/a"] + "#, + ) + .file( + "src/lib.rs", + "extern crate foo; pub fn bar() { foo::bar(); }", + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + a = [] + "#, + ) + .file("foo/src/lib.rs", r#"#[cfg(feature = "a")] pub fn bar() {}"#) + .build(); + + p.cargo("check --features a -v").run(); +} + +#[cargo_test] +fn activating_feature_does_not_activate_transitive_dev_dependency() { + let p = project() + .no_manifest() + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.0" + edition = "2021" + + [features] + f = ["b/f"] + + [dependencies] + b = { path = "../b" } + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.0" + edition = "2021" + + [features] + f = ["c/f"] + + [dev-dependencies] + c = { path = "../c" } + "#, + ) + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.0.0" + edition = "2021" + + [features] + f = [] + "#, + ) + .file("a/src/lib.rs", "") + .file("b/src/lib.rs", "") + .file("c/src/lib.rs", "compile_error!") + .build(); + + p.cargo("check --manifest-path a/Cargo.toml --features f") + .run(); +} + +#[cargo_test] +fn dep_feature_in_cmd_line() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.derived] + path = "derived" + "#, + ) + .file( + "src/main.rs", + r#" + extern crate derived; + fn main() { derived::test(); } + "#, + ) + .file( + "derived/Cargo.toml", + r#" + [package] + name = "derived" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + + [features] + default = [] + derived-feat = ["bar/some-feat"] + "#, + ) + .file("derived/src/lib.rs", "extern crate bar; pub use bar::test;") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + some-feat = [] + "#, + ) + .file( + "bar/src/lib.rs", + r#" + #[cfg(feature = "some-feat")] + pub fn test() { print!("test"); } + "#, + ) + .build(); + + // The foo project requires that feature "some-feat" in "bar" is enabled. + // Building without any features enabled should fail: + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... +error[E0432]: unresolved import `bar::test` +... +"#]]) + .run(); + + // We should be able to enable the feature "derived-feat", which enables "some-feat", + // on the command line. The feature is enabled, thus building should be successful: + p.cargo("check --features derived/derived-feat").run(); + + // Trying to enable features of transitive dependencies is an error + p.cargo("check --features bar/some-feat") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package `foo v0.0.1 ([ROOT]/foo)` does not have a dependency named `bar` + +"#]]) + .run(); + + // Hierarchical feature specification should still be disallowed + p.cargo("check --features derived/bar/some-feat") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] multiple slashes in feature `derived/bar/some-feat` is not allowed + +"#]]) + .run(); +} + +#[cargo_test] +fn all_features_flag_enables_all_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + foo = [] + bar = [] + + [dependencies.baz] + path = "baz" + optional = true + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(feature = "foo")] + pub fn foo() {} + + #[cfg(feature = "bar")] + pub fn bar() { + extern crate baz; + baz::baz(); + } + + fn main() { + foo(); + bar(); + } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check --all-features").run(); +} + +#[cargo_test] +fn many_cli_features_comma_delimited() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + optional = true + + [dependencies.baz] + path = "baz" + optional = true + "#, + ) + .file( + "src/main.rs", + r#" + #[allow(unused_extern_crates)] + extern crate bar; + #[allow(unused_extern_crates)] + extern crate baz; + fn main() {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check --features bar,baz") + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[CHECKING] baz v0.0.1 ([ROOT]/foo/baz) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn many_cli_features_comma_and_space_delimited() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + optional = true + + [dependencies.baz] + path = "baz" + optional = true + + [dependencies.bam] + path = "bam" + optional = true + + [dependencies.bap] + path = "bap" + optional = true + "#, + ) + .file( + "src/main.rs", + r#" + #[allow(unused_extern_crates)] + extern crate bar; + #[allow(unused_extern_crates)] + extern crate baz; + #[allow(unused_extern_crates)] + extern crate bam; + #[allow(unused_extern_crates)] + extern crate bap; + fn main() {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .file("bam/Cargo.toml", &basic_manifest("bam", "0.0.1")) + .file("bam/src/lib.rs", "pub fn bam() {}") + .file("bap/Cargo.toml", &basic_manifest("bap", "0.0.1")) + .file("bap/src/lib.rs", "pub fn bap() {}") + .build(); + + p.cargo("check --features") + .arg("bar,baz bam bap") + .with_stderr_data( + str![[r#" +[LOCKING] 4 packages to latest compatible versions +[CHECKING] bam v0.0.1 ([ROOT]/foo/bam) +[CHECKING] bap v0.0.1 ([ROOT]/foo/bap) +[CHECKING] bar v0.0.1 ([ROOT]/foo/bar) +[CHECKING] baz v0.0.1 ([ROOT]/foo/baz) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn only_dep_is_optional() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + foo = ['bar'] + + [dependencies] + bar = { version = "0.1", optional = true } + + [dev-dependencies] + bar = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn all_features_all_crates() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace] + members = ['bar'] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + foo = [] + "#, + ) + .file("bar/src/main.rs", "#[cfg(feature = \"foo\")] fn main() {}") + .build(); + + p.cargo("check --all-features --workspace").run(); +} + +#[cargo_test] +fn feature_off_dylib() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [lib] + crate-type = ["dylib"] + + [features] + f1 = [] + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn hello() -> &'static str { + if cfg!(feature = "f1") { + "f1" + } else { + "no f1" + } + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + + [dependencies] + foo = { path = ".." } + "#, + ) + .file( + "bar/src/main.rs", + r#" + extern crate foo; + + fn main() { + assert_eq!(foo::hello(), "no f1"); + } + "#, + ) + .build(); + + // Build the dylib with `f1` feature. + p.cargo("check --features f1").run(); + // Check that building without `f1` uses a dylib without `f1`. + p.cargo("run -p bar").run(); +} + +#[cargo_test] +fn warn_if_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + optional = true + + [features] + default-features = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] `default-features = [".."]` was found in [features]. Did you mean to use `default = [".."]`? +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn no_feature_for_non_optional_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(not(feature = "bar"))] + fn main() { + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + "#, + ) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("check --features bar/a").run(); +} + +#[cargo_test] +fn features_option_given_twice() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + b = [] + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(all(feature = "a", feature = "b"))] + fn main() {} + "#, + ) + .build(); + + p.cargo("check --features a --features b").run(); +} + +#[cargo_test] +fn multi_multi_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + b = [] + c = [] + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(all(feature = "a", feature = "b", feature = "c"))] + fn main() {} + "#, + ) + .build(); + + p.cargo("check --features a --features").arg("b c").run(); +} + +#[cargo_test] +fn cli_parse_ok() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(feature = "a")] + fn main() { + assert_eq!(std::env::args().nth(1).unwrap(), "b"); + } + "#, + ) + .build(); + + p.cargo("run --features a b").run(); +} + +#[cargo_test] +fn all_features_virtual_ws() { + // What happens with `--all-features` in the root of a virtual workspace. + // Some of this behavior is a little strange (member dependencies also + // have all features enabled, one might expect `f4` to be disabled). + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2018" + + [dependencies] + b = {path="../b", optional=true} + + [features] + default = ["f1"] + f1 = [] + f2 = [] + "#, + ) + .file( + "a/src/main.rs", + r#" + fn main() { + if cfg!(feature="f1") { + println!("f1"); + } + if cfg!(feature="f2") { + println!("f2"); + } + #[cfg(feature="b")] + b::f(); + } + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [features] + default = ["f3"] + f3 = [] + f4 = [] + "#, + ) + .file( + "b/src/lib.rs", + r#" + pub fn f() { + if cfg!(feature="f3") { + println!("f3"); + } + if cfg!(feature="f4") { + println!("f4"); + } + } + "#, + ) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +f1 + +"#]]) + .run(); + p.cargo("run --all-features") + .with_stdout_data(str![[r#" +f1 +f2 +f3 +f4 + +"#]]) + .run(); + // In `a`, it behaves differently. :( + p.cargo("run --all-features") + .cwd("a") + .with_stdout_data(str![[r#" +f1 +f2 +f3 + +"#]]) + .run(); +} + +#[cargo_test] +fn slash_optional_enables() { + // --features dep/feat will enable `dep` and set its feature. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = {path="dep", optional=true} + "#, + ) + .file( + "src/lib.rs", + r#" + #[cfg(not(feature="dep"))] + compile_error!("dep not set"); + "#, + ) + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + + [features] + feat = [] + "#, + ) + .file( + "dep/src/lib.rs", + r#" + #[cfg(not(feature="feat"))] + compile_error!("feat not set"); + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] dep not set +... +"#]]) + .run(); + + p.cargo("check --features dep/feat").run(); +} + +#[cargo_test] +fn registry_summary_order_doesnt_matter() { + // Checks for an issue where the resolver depended on the order of entries + // in the registry summary. If there was a non-optional dev-dependency + // that appeared before an optional normal dependency, then the resolver + // would not activate the optional dependency with a pkg/featname feature + // syntax. + Package::new("dep", "0.1.0") + .feature("feat1", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(feature="feat1")] + pub fn work() { + println!("it works"); + } + "#, + ) + .publish(); + Package::new("bar", "0.1.0") + .feature("bar_feat", &["dep/feat1"]) + .add_dep(Dependency::new("dep", "0.1.0").dev()) + .add_dep(Dependency::new("dep", "0.1.0").optional(true)) + .file( + "src/lib.rs", + r#" + // This will fail to compile without `dep` optional dep activated. + extern crate dep; + + pub fn doit() { + dep::work(); + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + bar = { version="0.1", features = ["bar_feat"] } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + bar::doit(); + } + "#, + ) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[COMPILING] dep v0.1.0 +[COMPILING] bar v0.1.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +it works + +"#]]) + .run(); +} + +#[cargo_test] +fn nonexistent_required_features() { + Package::new("required_dependency", "0.1.0") + .feature("simple", &[]) + .publish(); + Package::new("optional_dependency", "0.2.0") + .feature("optional", &[]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [features] + existing = [] + fancy = ["optional_dependency"] + [dependencies] + required_dependency = { version = "0.1", optional = false} + optional_dependency = { version = "0.2", optional = true} + [[example]] + name = "ololo" + required-features = ["not_present", + "existing", + "fancy", + "required_dependency/not_existing", + "required_dependency/simple", + "optional_dependency/optional", + "not_specified_dependency/some_feature"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("examples/ololo.rs", "fn main() {}") + .build(); + + p.cargo("check --examples").with_stderr_data(str![[r#" +... +[WARNING] invalid feature `not_present` in required-features of target `ololo`: `not_present` is not present in [features] section +[WARNING] invalid feature `required_dependency/not_existing` in required-features of target `ololo`: feature `not_existing` does not exist in package `required_dependency v0.1.0` +[WARNING] invalid feature `not_specified_dependency/some_feature` in required-features of target `ololo`: dependency `not_specified_dependency` does not exist +... +"#]]).run(); +} + +#[cargo_test] +fn invalid_feature_names_error() { + // Errors for more restricted feature syntax. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + # Invalid start character. + "+foo" = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character `+` in feature name: `+foo`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`) + --> Cargo.toml:9:17 + | +9 | "+foo" = [] + | ^^^^^^ + | + +"#]]) + .run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + # Invalid continue character. + "a&b" = [] + "#, + ); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character `&` in feature name: `a&b`, characters must be Unicode XID characters, '-', `+`, or `.` (numbers, `+`, `-`, `_`, `.`, or most letters) + --> Cargo.toml:9:13 + | +9 | "a&b" = [] + | ^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_feature_name_slash_error() { + // Errors for more restricted feature syntax. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + "foo/bar" = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character `/` in feature name: `foo/bar`, feature name is not allowed to contain slashes + --> Cargo.toml:8:17 + | +8 | "foo/bar" = [] + | ^^^^^^^^^ + | + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features2.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features2.rs new file mode 100644 index 000000000..279f62511 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features2.rs @@ -0,0 +1,2818 @@ +//! Tests for the new feature resolver. + +use std::fs::File; + +use cargo_test_support::cross_compile::{self, alternate}; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::publish::validate_crate_contents; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, cargo_process, project, rustc_host, Project}; + +/// Switches Cargo.toml to use `resolver = "2"`. +pub fn switch_to_resolver_2(p: &Project) { + let mut manifest = p.read_file("Cargo.toml"); + if manifest.contains("resolver =") { + panic!("did not expect manifest to already contain a resolver setting"); + } + if let Some(index) = manifest.find("[workspace]\n") { + manifest.insert_str(index + 12, "resolver = \"2\"\n"); + } else if let Some(index) = manifest.find("[package]\n") { + manifest.insert_str(index + 10, "resolver = \"2\"\n"); + } else { + panic!("expected [package] or [workspace] in manifest"); + } + p.change_file("Cargo.toml", &manifest); +} + +#[cargo_test] +fn inactivate_targets() { + // Basic test of `itarget`. A shared dependency where an inactive [target] + // changes the features. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(feature = "f1")] + compile_error!("f1 should not activate"); + "#, + ) + .publish(); + + Package::new("bar", "1.0.0") + .add_dep( + Dependency::new("common", "1.0") + .target("cfg(whatever)") + .enable_features(&["f1"]), + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + common = "1.0" + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data( + str![[r#" +... +[ERROR] f1 should not activate +... +"#]] + .unordered(), + ) + .run(); + + switch_to_resolver_2(&p); + p.cargo("check").run(); +} + +#[cargo_test] +fn inactive_target_optional() { + // Activating optional [target] dependencies for inactivate target. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .feature("f2", &[]) + .feature("f3", &[]) + .feature("f4", &[]) + .file( + "src/lib.rs", + r#" + pub fn f() { + if cfg!(feature="f1") { println!("f1"); } + if cfg!(feature="f2") { println!("f2"); } + if cfg!(feature="f3") { println!("f3"); } + if cfg!(feature="f4") { println!("f4"); } + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + common = "1.0" + + [target.'cfg(whatever)'.dependencies] + dep1 = {path='dep1', optional=true} + dep2 = {path='dep2', optional=true, features=["f3"]} + common = {version="1.0", optional=true, features=["f4"]} + + [features] + foo1 = ["dep1/f2"] + foo2 = ["dep2"] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(feature="foo1") { println!("foo1"); } + if cfg!(feature="foo2") { println!("foo2"); } + if cfg!(feature="dep1") { println!("dep1"); } + if cfg!(feature="dep2") { println!("dep2"); } + if cfg!(feature="common") { println!("common"); } + common::f(); + } + "#, + ) + .file( + "dep1/Cargo.toml", + r#" + [package] + name = "dep1" + version = "0.1.0" + edition = "2015" + + [dependencies] + common = {version="1.0", features=["f1"]} + + [features] + f2 = ["common/f2"] + "#, + ) + .file( + "dep1/src/lib.rs", + r#"compile_error!("dep1 should not build");"#, + ) + .file( + "dep2/Cargo.toml", + r#" + [package] + name = "dep2" + version = "0.1.0" + edition = "2015" + + [dependencies] + common = "1.0" + + [features] + f3 = ["common/f3"] + "#, + ) + .file( + "dep2/src/lib.rs", + r#"compile_error!("dep2 should not build");"#, + ) + .build(); + + p.cargo("run --all-features") + .with_stdout_data(str![[r#" +foo1 +foo2 +dep1 +dep2 +common +f1 +f2 +f3 +f4 + +"#]]) + .run(); + p.cargo("run --features dep1") + .with_stdout_data(str![[r#" +dep1 +f1 + +"#]]) + .run(); + p.cargo("run --features foo1") + .with_stdout_data(str![[r#" +foo1 +dep1 +f1 +f2 + +"#]]) + .run(); + p.cargo("run --features dep2") + .with_stdout_data(str![[r#" +dep2 +f3 + +"#]]) + .run(); + p.cargo("run --features common") + .with_stdout_data(str![[r#" +common +f4 + +"#]]) + .run(); + + switch_to_resolver_2(&p); + p.cargo("run --all-features") + .with_stdout_data(str![[r#" +foo1 +foo2 +dep1 +dep2 +common + +"#]]) + .run(); + p.cargo("run --features dep1") + .with_stdout_data(str![[r#" +dep1 + +"#]]) + .run(); + p.cargo("run --features foo1") + .with_stdout_data(str![[r#" +foo1 + +"#]]) + .run(); + p.cargo("run --features dep2") + .with_stdout_data(str![[r#" +dep2 + +"#]]) + .run(); + p.cargo("run --features common") + .with_stdout_data(str![[r#" +common + +"#]]) + .run(); +} + +#[cargo_test] +fn itarget_proc_macro() { + // itarget inside a proc-macro while cross-compiling + if cross_compile::disabled() { + return; + } + Package::new("hostdep", "1.0.0").publish(); + Package::new("pm", "1.0.0") + .proc_macro(true) + .target_dep("hostdep", "1.0", rustc_host()) + .file("src/lib.rs", "extern crate hostdep;") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + pm = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Old behavior + p.cargo("check").run(); + p.cargo("check --target").arg(alternate()).run(); + + // New behavior + switch_to_resolver_2(&p); + p.cargo("check").run(); + p.cargo("check --target").arg(alternate()).run(); + // For good measure, just make sure things don't break. + p.cargo("check --target").arg(alternate()).run(); +} + +#[cargo_test] +fn decouple_host_deps() { + // Basic test for `host_dep` decouple. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(feature = "f1")] + pub fn foo() {} + #[cfg(not(feature = "f1"))] + pub fn bar() {} + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [build-dependencies] + common = {version="1.0", features=["f1"]} + + [dependencies] + common = "1.0" + "#, + ) + .file( + "build.rs", + r#" + use common::foo; + fn main() {} + "#, + ) + .file("src/lib.rs", "use common::bar;") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... +error[E0432]: unresolved import `common::bar` +... +"#]]) + .run(); + + switch_to_resolver_2(&p); + p.cargo("check").run(); +} + +#[cargo_test] +fn decouple_host_deps_nested() { + // `host_dep` decouple of transitive dependencies. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(feature = "f1")] + pub fn foo() {} + #[cfg(not(feature = "f1"))] + pub fn bar() {} + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [build-dependencies] + bdep = {path="bdep"} + + [dependencies] + common = "1.0" + "#, + ) + .file( + "build.rs", + r#" + use bdep::foo; + fn main() {} + "#, + ) + .file("src/lib.rs", "use common::bar;") + .file( + "bdep/Cargo.toml", + r#" + [package] + name = "bdep" + version = "0.1.0" + edition = "2018" + + [dependencies] + common = {version="1.0", features=["f1"]} + "#, + ) + .file("bdep/src/lib.rs", "pub use common::foo;") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... +error[E0432]: unresolved import `common::bar` +... +"#]]) + .run(); + + switch_to_resolver_2(&p); + p.cargo("check").run(); +} + +#[cargo_test] +fn decouple_dev_deps() { + // Basic test for `dev_dep` decouple. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .feature("f2", &[]) + .file( + "src/lib.rs", + r#" + // const ensures it uses the correct dependency at *build time* + // compared to *link time*. + #[cfg(all(feature="f1", not(feature="f2")))] + pub const X: u32 = 1; + + #[cfg(all(feature="f1", feature="f2"))] + pub const X: u32 = 3; + + pub fn foo() -> u32 { + let mut res = 0; + if cfg!(feature = "f1") { + res |= 1; + } + if cfg!(feature = "f2") { + res |= 2; + } + res + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + common = {version="1.0", features=["f1"]} + + [dev-dependencies] + common = {version="1.0", features=["f2"]} + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + let expected: u32 = std::env::args().skip(1).next().unwrap().parse().unwrap(); + assert_eq!(foo::foo(), expected); + assert_eq!(foo::build_time(), expected); + assert_eq!(common::foo(), expected); + assert_eq!(common::X, expected); + } + + #[test] + fn test_bin() { + assert_eq!(foo::foo(), 3); + assert_eq!(common::foo(), 3); + assert_eq!(common::X, 3); + assert_eq!(foo::build_time(), 3); + } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { + common::foo() + } + + pub fn build_time() -> u32 { + common::X + } + + #[test] + fn test_lib() { + assert_eq!(foo(), 3); + assert_eq!(common::foo(), 3); + assert_eq!(common::X, 3); + } + "#, + ) + .file( + "tests/t1.rs", + r#" + #[test] + fn test_t1() { + assert_eq!(foo::foo(), 3); + assert_eq!(common::foo(), 3); + assert_eq!(common::X, 3); + assert_eq!(foo::build_time(), 3); + } + + #[test] + fn test_main() { + // Features are unified for main when run with `cargo test`, + // even with the new resolver. + let s = std::process::Command::new("target/debug/foo") + .arg("3") + .status().unwrap(); + assert!(s.success()); + } + "#, + ) + .build(); + + // Old behavior + p.cargo("run 3").run(); + p.cargo("test").run(); + + // New behavior + switch_to_resolver_2(&p); + p.cargo("run 1").run(); + p.cargo("test").run(); +} + +#[cargo_test] +fn build_script_runtime_features() { + // Check that the CARGO_FEATURE_* environment variable is set correctly. + // + // This has a common dependency between build/normal/dev-deps, and it + // queries which features it was built with in different circumstances. + Package::new("common", "1.0.0") + .feature("normal", &[]) + .feature("dev", &[]) + .feature("build", &[]) + .file( + "build.rs", + r#" + fn is_set(name: &str) -> bool { + std::env::var(name) == Ok("1".to_string()) + } + + fn main() { + let mut res = 0; + if is_set("CARGO_FEATURE_NORMAL") { + res |= 1; + } + if is_set("CARGO_FEATURE_DEV") { + res |= 2; + } + if is_set("CARGO_FEATURE_BUILD") { + res |= 4; + } + println!("cargo::rustc-cfg=RunCustomBuild=\"{}\"", res); + + let mut res = 0; + if cfg!(feature = "normal") { + res |= 1; + } + if cfg!(feature = "dev") { + res |= 2; + } + if cfg!(feature = "build") { + res |= 4; + } + println!("cargo::rustc-cfg=CustomBuild=\"{}\"", res); + } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { + let mut res = 0; + if cfg!(feature = "normal") { + res |= 1; + } + if cfg!(feature = "dev") { + res |= 2; + } + if cfg!(feature = "build") { + res |= 4; + } + res + } + + pub fn build_time() -> u32 { + #[cfg(RunCustomBuild="1")] return 1; + #[cfg(RunCustomBuild="3")] return 3; + #[cfg(RunCustomBuild="4")] return 4; + #[cfg(RunCustomBuild="5")] return 5; + #[cfg(RunCustomBuild="7")] return 7; + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [build-dependencies] + common = {version="1.0", features=["build"]} + + [dependencies] + common = {version="1.0", features=["normal"]} + + [dev-dependencies] + common = {version="1.0", features=["dev"]} + "#, + ) + .file( + "build.rs", + r#" + fn main() { + assert_eq!(common::foo(), common::build_time()); + println!("cargo::rustc-cfg=from_build=\"{}\"", common::foo()); + } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { + common::foo() + } + + pub fn build_time() -> u32 { + common::build_time() + } + + #[test] + fn test_lib() { + assert_eq!(common::foo(), common::build_time()); + assert_eq!(common::foo(), + std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap()); + } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + assert_eq!(common::foo(), common::build_time()); + assert_eq!(common::foo(), + std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap()); + } + + #[test] + fn test_bin() { + assert_eq!(common::foo(), common::build_time()); + assert_eq!(common::foo(), + std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap()); + } + "#, + ) + .file( + "tests/t1.rs", + r#" + #[test] + fn test_t1() { + assert_eq!(common::foo(), common::build_time()); + assert_eq!(common::foo(), + std::env::var("CARGO_FEATURE_EXPECT").unwrap().parse().unwrap()); + } + + #[test] + fn test_main() { + // Features are unified for main when run with `cargo test`, + // even with the new resolver. + let s = std::process::Command::new("target/debug/foo") + .status().unwrap(); + assert!(s.success()); + } + "#, + ) + .build(); + + // Old way, unifies all 3. + p.cargo("run").env("CARGO_FEATURE_EXPECT", "7").run(); + p.cargo("test").env("CARGO_FEATURE_EXPECT", "7").run(); + + // New behavior. + switch_to_resolver_2(&p); + + // normal + build unify + p.cargo("run").env("CARGO_FEATURE_EXPECT", "1").run(); + + // dev_deps are still unified with `cargo test` + p.cargo("test").env("CARGO_FEATURE_EXPECT", "3").run(); +} + +#[cargo_test] +fn cyclical_dev_dep() { + // Check how a cyclical dev-dependency will work. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [features] + dev = [] + + [dev-dependencies] + foo = { path = '.', features = ["dev"] } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn assert_dev(enabled: bool) { + assert_eq!(enabled, cfg!(feature="dev")); + } + + #[test] + fn test_in_lib() { + assert_dev(true); + } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + let expected: bool = std::env::args().skip(1).next().unwrap().parse().unwrap(); + foo::assert_dev(expected); + } + "#, + ) + .file( + "tests/t1.rs", + r#" + #[test] + fn integration_links() { + foo::assert_dev(true); + // The lib linked with main.rs will also be unified. + let s = std::process::Command::new("target/debug/foo") + .arg("true") + .status().unwrap(); + assert!(s.success()); + } + "#, + ) + .build(); + + // Old way unifies features. + p.cargo("run true").run(); + // dev feature should always be enabled in tests. + p.cargo("test").run(); + + // New behavior. + switch_to_resolver_2(&p); + // Should decouple main. + p.cargo("run false").run(); + + // And this should be no different. + p.cargo("test").run(); +} + +#[cargo_test] +fn all_feature_opts() { + // All feature options at once. + Package::new("common", "1.0.0") + .feature("normal", &[]) + .feature("build", &[]) + .feature("dev", &[]) + .feature("itarget", &[]) + .file( + "src/lib.rs", + r#" + pub fn feats() -> u32 { + let mut res = 0; + if cfg!(feature="normal") { res |= 1; } + if cfg!(feature="build") { res |= 2; } + if cfg!(feature="dev") { res |= 4; } + if cfg!(feature="itarget") { res |= 8; } + res + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + common = {version = "1.0", features=["normal"]} + + [dev-dependencies] + common = {version = "1.0", features=["dev"]} + + [build-dependencies] + common = {version = "1.0", features=["build"]} + + [target.'cfg(whatever)'.dependencies] + common = {version = "1.0", features=["itarget"]} + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + expect(); + } + + fn expect() { + let expected: u32 = std::env::var("EXPECTED_FEATS").unwrap().parse().unwrap(); + assert_eq!(expected, common::feats()); + } + + #[test] + fn from_test() { + expect(); + } + "#, + ) + .build(); + + p.cargo("run").env("EXPECTED_FEATS", "15").run(); + p.cargo("test").env("EXPECTED_FEATS", "15").run(); + + // New behavior. + switch_to_resolver_2(&p); + // Only normal feature. + p.cargo("run").env("EXPECTED_FEATS", "1").run(); + + // only normal+dev + p.cargo("test").env("EXPECTED_FEATS", "5").run(); +} + +#[cargo_test] +fn required_features_host_dep() { + // Check that required-features handles build-dependencies correctly. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [[bin]] + name = "x" + required-features = ["bdep/f1"] + + [build-dependencies] + bdep = {path="bdep"} + "#, + ) + .file("build.rs", "fn main() {}") + .file( + "src/bin/x.rs", + r#" + fn main() {} + "#, + ) + .file( + "bdep/Cargo.toml", + r#" + [package] + name = "bdep" + version = "0.1.0" + edition = "2015" + + [features] + f1 = [] + "#, + ) + .file("bdep/src/lib.rs", "") + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] target `x` in package `foo` requires the features: `bdep/f1` +Consider enabling them by passing, e.g., `--features="bdep/f1"` + +"#]]) + .run(); + + // New behavior. + switch_to_resolver_2(&p); + p.cargo("run --features bdep/f1").run(); +} + +#[cargo_test] +fn disabled_shared_host_dep() { + // Check for situation where an optional dep of a shared dep is enabled in + // a normal dependency, but disabled in an optional one. The unit tree is: + // foo + // ├── foo build.rs + // | └── common (BUILD dependency, NO FEATURES) + // └── common (Normal dependency, default features) + // └── somedep + Package::new("somedep", "1.0.0") + .file( + "src/lib.rs", + r#" + pub fn f() { println!("hello from somedep"); } + "#, + ) + .publish(); + Package::new("common", "1.0.0") + .feature("default", &["somedep"]) + .add_dep(Dependency::new("somedep", "1.0").optional(true)) + .file( + "src/lib.rs", + r#" + pub fn check_somedep() -> bool { + #[cfg(feature="somedep")] + { + extern crate somedep; + somedep::f(); + true + } + #[cfg(not(feature="somedep"))] + { + println!("no somedep"); + false + } + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2018" + resolver = "2" + + [dependencies] + common = "1.0" + + [build-dependencies] + common = {version = "1.0", default-features = false} + "#, + ) + .file( + "src/main.rs", + "fn main() { assert!(common::check_somedep()); }", + ) + .file( + "build.rs", + "fn main() { assert!(!common::check_somedep()); }", + ) + .build(); + + p.cargo("run -v") + .with_stdout_data(str![[r#" +hello from somedep + +"#]]) + .run(); +} + +#[cargo_test] +fn required_features_inactive_dep() { + // required-features with an inactivated dep. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [target.'cfg(whatever)'.dependencies] + bar = {path="bar"} + + [[bin]] + name = "foo" + required-features = ["feat1"] + + [features] + feat1 = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check --features=feat1") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn decouple_proc_macro() { + // proc macro features are not shared + Package::new("common", "1.0.0") + .feature("somefeat", &[]) + .file( + "src/lib.rs", + r#" + pub const fn foo() -> bool { cfg!(feature="somefeat") } + #[cfg(feature="somefeat")] + pub const FEAT_ONLY_CONST: bool = true; + "#, + ) + .publish(); + Package::new("pm", "1.0.0") + .proc_macro(true) + .feature_dep("common", "1.0", &["somefeat"]) + .file( + "src/lib.rs", + r#" + extern crate proc_macro; + extern crate common; + #[proc_macro] + pub fn foo(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + assert!(common::foo()); + "".parse().unwrap() + } + "#, + ) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2018" + + [dependencies] + pm = "1.0" + common = "1.0" + "#, + ) + .file( + "src/lib.rs", + r#" + //! Test with docs. + //! + //! ```rust + //! pm::foo!{} + //! fn main() { + //! let expected = std::env::var_os("TEST_EXPECTS_ENABLED").is_some(); + //! assert_eq!(expected, common::foo(), "common is wrong"); + //! } + //! ``` + "#, + ) + .file( + "src/main.rs", + r#" + pm::foo!{} + fn main() { + println!("it is {}", common::foo()); + } + "#, + ) + .build(); + + p.cargo("run") + .env("TEST_EXPECTS_ENABLED", "1") + .with_stdout_data(str![[r#" +it is true + +"#]]) + .run(); + // Make sure the test is fallible. + p.cargo("test --doc") + .with_status(101) + .with_stdout_data("...\n[..]common is wrong[..]\n...") + .run(); + p.cargo("test --doc").env("TEST_EXPECTS_ENABLED", "1").run(); + p.cargo("doc").run(); + assert!(p + .build_dir() + .join("doc/common/constant.FEAT_ONLY_CONST.html") + .exists()); + // cargo doc should clean in-between runs, but it doesn't, and leaves stale files. + // https://github.com/rust-lang/cargo/issues/6783 (same for removed items) + p.build_dir().join("doc").rm_rf(); + + // New behavior. + switch_to_resolver_2(&p); + p.cargo("run") + .with_stdout_data(str![[r#" +it is false + +"#]]) + .run(); + + p.cargo("test --doc").run(); + p.cargo("doc").run(); + assert!(!p + .build_dir() + .join("doc/common/constant.FEAT_ONLY_CONST.html") + .exists()); +} + +#[cargo_test] +fn proc_macro_ws() { + // Checks for bug with proc-macro in a workspace with dependency (shouldn't panic). + // + // Note, debuginfo is explicitly requested here to preserve the intent of this non-regression + // test: that will disable the debuginfo build dependencies optimization. Otherwise, it would + // initially trigger when the crates are built independently, but rebuild them with debuginfo + // when it sees the shared build/runtime dependency when checking the complete workspace. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "pm"] + resolver = "2" + + [profile.dev.build-override] + debug = true + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + feat1 = [] + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + foo = { path = "../foo", features=["feat1"] } + "#, + ) + .file("pm/src/lib.rs", "") + .build(); + + p.cargo("check -p pm -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustc --crate-name foo [..]--cfg[..]feat1[..]` +... +"#]]) + .run(); + // This may be surprising that `foo` doesn't get built separately. It is + // because pm might have other units (binaries, tests, etc.), and so the + // feature resolver must assume that normal deps get unified with it. This + // is related to the bigger issue where the features selected in a + // workspace depend on which packages are selected. + p.cargo("check --workspace -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.1.0 ([ROOT]/foo/foo) +[FRESH] pm v0.1.0 ([ROOT]/foo/pm) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // Selecting just foo will build without unification. + p.cargo("check -p foo -v") + // Make sure `foo` is built without feat1 + .with_stderr_line_without( + &["[RUNNING] `rustc --crate-name foo --edition=2015"], + &["--cfg[..]feat1"], + ) + .run(); +} + +#[cargo_test] +fn has_dev_dep_for_test() { + // Check for a bug where the decision on whether or not "dev dependencies" + // should be used did not consider `check --profile=test`. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dev-dependencies] + dep = { path = 'dep', features = ['f1'] } + "#, + ) + .file( + "src/lib.rs", + r#" + #[test] + fn t1() { + dep::f(); + } + "#, + ) + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + + [features] + f1 = [] + "#, + ) + .file( + "dep/src/lib.rs", + r#" + #[cfg(feature = "f1")] + pub fn f() {} + "#, + ) + .build(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -v --profile=test") + .with_stderr_data(str![[r#" +[CHECKING] dep v0.1.0 ([ROOT]/foo/dep) +[RUNNING] `rustc --crate-name dep [..]` +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // New resolver should not be any different. + switch_to_resolver_2(&p); + p.cargo("check -v --profile=test") + .with_stderr_data(str![[r#" +[FRESH] dep v0.1.0 ([ROOT]/foo/dep) +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_dep_activated() { + // Build dependencies always match the host for [target.*.build-dependencies]. + if cross_compile::disabled() { + return; + } + Package::new("somedep", "1.0.0") + .file("src/lib.rs", "") + .publish(); + Package::new("targetdep", "1.0.0").publish(); + Package::new("hostdep", "1.0.0") + // Check that "for_host" is sticky. + .target_dep("somedep", "1.0", rustc_host()) + .feature("feat1", &[]) + .file( + "src/lib.rs", + r#" + extern crate somedep; + + #[cfg(not(feature="feat1"))] + compile_error!{"feat1 missing"} + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + # This should never be selected. + [target.'{}'.build-dependencies] + targetdep = "1.0" + + [target.'{}'.build-dependencies] + hostdep = {{version="1.0", features=["feat1"]}} + "#, + alternate(), + rustc_host() + ), + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); + p.cargo("check --target").arg(alternate()).run(); + + // New behavior. + switch_to_resolver_2(&p); + p.cargo("check").run(); + p.cargo("check --target").arg(alternate()).run(); +} + +#[cargo_test] +fn resolver_bad_setting() { + // Unknown setting in `resolver` + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `resolver` setting `foo` is not valid, valid options are "1" or "2" + +"#]]) + .run(); +} + +#[cargo_test] +fn resolver_original() { + // resolver="1" uses old unification behavior. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(feature = "f1")] + compile_error!("f1 should not activate"); + "#, + ) + .publish(); + + Package::new("bar", "1.0.0") + .add_dep( + Dependency::new("common", "1.0") + .target("cfg(whatever)") + .enable_features(&["f1"]), + ) + .publish(); + + let manifest = |resolver| { + format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "{}" + + [dependencies] + common = "1.0" + bar = "1.0" + "#, + resolver + ) + }; + + let p = project() + .file("Cargo.toml", &manifest("1")) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data( + str![[r#" +... +[ERROR] f1 should not activate +... +"#]] + .unordered(), + ) + .run(); + + p.change_file("Cargo.toml", &manifest("2")); + + p.cargo("check").run(); +} + +#[cargo_test] +fn resolver_not_both() { + // Can't specify resolver in both workspace and package. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + resolver = "2" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + cannot specify `resolver` field in both `[workspace]` and `[package]` + +"#]]) + .run(); +} + +#[cargo_test] +fn resolver_ws_member() { + // Can't specify `resolver` in a ws member. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + resolver = "2" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] resolver for the non root package will be ignored, specify resolver at the workspace root: +package: [ROOT]/foo/a/Cargo.toml +workspace: [ROOT]/foo/Cargo.toml +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn edition_2021_workspace_member() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2021" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[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 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn resolver_ws_root_and_member() { + // Check when specified in both ws root and member. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + resolver = "2" + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + resolver = "2" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + // Ignores if they are the same. + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn resolver_enables_new_features() { + // resolver="2" enables all the things. + Package::new("common", "1.0.0") + .feature("normal", &[]) + .feature("build", &[]) + .feature("dev", &[]) + .feature("itarget", &[]) + .file( + "src/lib.rs", + r#" + pub fn feats() -> u32 { + let mut res = 0; + if cfg!(feature="normal") { res |= 1; } + if cfg!(feature="build") { res |= 2; } + if cfg!(feature="dev") { res |= 4; } + if cfg!(feature="itarget") { res |= 8; } + res + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + resolver = "2" + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2018" + + [dependencies] + common = {version = "1.0", features=["normal"]} + + [dev-dependencies] + common = {version = "1.0", features=["dev"]} + + [build-dependencies] + common = {version = "1.0", features=["build"]} + + [target.'cfg(whatever)'.dependencies] + common = {version = "1.0", features=["itarget"]} + "#, + ) + .file( + "a/src/main.rs", + r#" + fn main() { + expect(); + } + + fn expect() { + let expected: u32 = std::env::var("EXPECTED_FEATS").unwrap().parse().unwrap(); + assert_eq!(expected, common::feats()); + } + + #[test] + fn from_test() { + expect(); + } + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [features] + ping = [] + "#, + ) + .file( + "b/src/main.rs", + r#" + fn main() { + if cfg!(feature="ping") { + println!("pong"); + } + } + "#, + ) + .build(); + + // Only normal. + p.cargo("run --bin a") + .env("EXPECTED_FEATS", "1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] common v1.0.0 (registry `dummy-registry`) +[COMPILING] common v1.0.0 +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/a[EXE]` + +"#]]) + .run(); + + // only normal+dev + p.cargo("test").cwd("a").env("EXPECTED_FEATS", "5").run(); + + // Can specify features of packages from a different directory. + p.cargo("run -p b --features=ping") + .cwd("a") + .with_stdout_data(str![[r#" +pong + +"#]]) + .run(); +} + +#[cargo_test] +fn install_resolve_behavior() { + // install honors the resolver behavior. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(feature = "f1")] + compile_error!("f1 should not activate"); + "#, + ) + .publish(); + + Package::new("bar", "1.0.0").dep("common", "1.0").publish(); + + Package::new("foo", "1.0.0") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + resolver = "2" + + [target.'cfg(whatever)'.dependencies] + common = {version="1.0", features=["f1"]} + + [dependencies] + bar = "1.0" + + "#, + ) + .file("src/main.rs", "fn main() {}") + .publish(); + + cargo_process("install foo").run(); +} + +#[cargo_test] +fn package_includes_resolve_behavior() { + // `cargo package` will inherit the correct resolve behavior. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + resolver = "2" + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + authors = ["Zzz"] + description = "foo" + license = "MIT" + homepage = "https://example.com/" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("package").cwd("a").run(); + + let rewritten_toml = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "a" +version = "0.1.0" +authors = ["Zzz"] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "https://example.com/" +readme = false +license = "MIT" +resolver = "2" + +[lib] +name = "a" +path = "src/lib.rs" + +"##]]; + + let f = File::open(&p.root().join("target/package/a-0.1.0.crate")).unwrap(); + validate_crate_contents( + f, + "a-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [("Cargo.toml", rewritten_toml)], + ); +} + +#[cargo_test] +fn tree_all() { + // `cargo tree` with the new feature resolver. + Package::new("log", "0.4.8").feature("serde", &[]).publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [target.'cfg(whatever)'.dependencies] + log = {version="*", features=["serde"]} + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("tree --target=all") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── log v0.4.8 + +"#]]) + .run(); +} + +#[cargo_test] +fn shared_dep_same_but_dependencies() { + // Checks for a bug of nondeterminism. This scenario creates a shared + // dependency `dep` which needs to be built twice (once as normal, and + // once as a build dep). However, in both cases the flags to `dep` are the + // same, the only difference is what it links to. The normal dependency + // should link to `subdep` with the feature disabled, and the build + // dependency should link to it with it enabled. Crucially, the `--target` + // flag should not be specified, otherwise Unit.kind would be different + // and avoid the collision, and this bug won't manifest. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bin1", "bin2"] + resolver = "2" + "#, + ) + .file( + "bin1/Cargo.toml", + r#" + [package] + name = "bin1" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = { path = "../dep" } + "#, + ) + .file("bin1/src/main.rs", "fn main() { dep::feat_func(); }") + .file( + "bin2/Cargo.toml", + r#" + [package] + name = "bin2" + version = "0.1.0" + edition = "2015" + + [build-dependencies] + dep = { path = "../dep" } + subdep = { path = "../subdep", features = ["feat"] } + "#, + ) + .file("bin2/build.rs", "fn main() { dep::feat_func(); }") + .file("bin2/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + + [dependencies] + subdep = { path = "../subdep" } + "#, + ) + .file( + "dep/src/lib.rs", + "pub fn feat_func() { subdep::feat_func(); }", + ) + .file( + "subdep/Cargo.toml", + r#" + [package] + name = "subdep" + version = "0.1.0" + edition = "2015" + + [features] + feat = [] + "#, + ) + .file( + "subdep/src/lib.rs", + r#" + pub fn feat_func() { + #[cfg(feature = "feat")] println!("cargo::warning=feat: enabled"); + #[cfg(not(feature = "feat"))] println!("cargo::warning=feat: not enabled"); + } + "#, + ) + .build(); + + p.cargo("build --bin bin1 --bin bin2") + // unordered because bin1 and bin2 build at the same time + .with_stderr_data( + str![[r#" +[COMPILING] subdep v0.1.0 ([ROOT]/foo/subdep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] bin1 v0.1.0 ([ROOT]/foo/bin1) +[COMPILING] bin2 v0.1.0 ([ROOT]/foo/bin2) +[WARNING] bin2@0.1.0: feat: enabled +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + p.process(p.bin("bin1")) + .with_stdout_data(str![[r#" +cargo::warning=feat: not enabled + +"#]]) + .run(); + + // Make sure everything stays cached. + p.cargo("build -v --bin bin1 --bin bin2") + .with_stderr_data( + str![[r#" +[FRESH] subdep v0.1.0 ([ROOT]/foo/subdep) +[FRESH] dep v0.1.0 ([ROOT]/foo/dep) +[FRESH] bin1 v0.1.0 ([ROOT]/foo/bin1) +[WARNING] bin2@0.1.0: feat: enabled +[FRESH] bin2 v0.1.0 ([ROOT]/foo/bin2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_proc_macro() { + // Running `cargo test` on a proc-macro, with a shared dependency that has + // different features. + // + // There was a bug where `shared` was built twice (once with feature "B" + // and once without), and both copies linked into the unit test. This + // would cause a type failure when used in an intermediate dependency + // (the-macro-support). + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "runtime" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [dependencies] + the-macro = { path = "the-macro", features = ['a'] } + [build-dependencies] + shared = { path = "shared", features = ['b'] } + "#, + ) + .file("src/lib.rs", "") + .file( + "the-macro/Cargo.toml", + r#" + [package] + name = "the-macro" + version = "0.1.0" + edition = "2015" + [lib] + proc-macro = true + test = false + [dependencies] + the-macro-support = { path = "../the-macro-support" } + shared = { path = "../shared" } + [dev-dependencies] + runtime = { path = ".." } + [features] + a = [] + "#, + ) + .file( + "the-macro/src/lib.rs", + " + fn _test() { + the_macro_support::foo(shared::Foo); + } + ", + ) + .file( + "the-macro-support/Cargo.toml", + r#" + [package] + name = "the-macro-support" + version = "0.1.0" + edition = "2015" + [dependencies] + shared = { path = "../shared" } + "#, + ) + .file( + "the-macro-support/src/lib.rs", + " + pub fn foo(_: shared::Foo) {} + ", + ) + .file( + "shared/Cargo.toml", + r#" + [package] + name = "shared" + version = "0.1.0" + edition = "2015" + [features] + b = [] + "#, + ) + .file("shared/src/lib.rs", "pub struct Foo;") + .build(); + p.cargo("test --manifest-path the-macro/Cargo.toml").run(); +} + +#[cargo_test] +fn doc_optional() { + // Checks for a bug where `cargo doc` was failing with an inactive target + // that enables a shared optional dependency. + Package::new("spin", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("spin", "1.0").optional(true)) + .publish(); + // The enabler package enables the `spin` feature, which we don't want. + Package::new("enabler", "1.0.0") + .feature_dep("bar", "1.0", &["spin"]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [target.'cfg(whatever)'.dependencies] + enabler = "1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] spin v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[DOCUMENTING] bar v1.0.0 +[CHECKING] bar v1.0.0 +[DOCUMENTING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn minimal_download() { + // Various checks that it only downloads the minimum set of dependencies + // needed in various situations. + // + // This checks several permutations of the different + // host_dep/dev_dep/itarget settings. These 3 are planned to be stabilized + // together, so there isn't much need to be concerned about how the behave + // independently. However, there are some cases where they do behave + // independently. Specifically: + // + // * `cargo test` forces dev_dep decoupling to be disabled. + // * `cargo tree --target=all` forces ignore_inactive_targets off and decouple_dev_deps off. + // * `cargo tree --target=all -e normal` forces ignore_inactive_targets off. + // + // However, `cargo tree` is a little weird because it downloads everything + // anyways. + // + // So to summarize the different permutations: + // + // dev_dep | host_dep | itarget | Notes + // --------|----------|---------|---------------------------- + // | | | -Zfeatures=compare (new resolver should behave same as old) + // | | ✓ | This scenario should not happen. + // | ✓ | | `cargo tree --target=all -Zfeatures=all`† + // | ✓ | ✓ | `cargo test` + // ✓ | | | This scenario should not happen. + // ✓ | | ✓ | This scenario should not happen. + // ✓ | ✓ | | `cargo tree --target=all -e normal -Z features=all`† + // ✓ | ✓ | ✓ | A normal build. + // + // † — However, `cargo tree` downloads everything. + Package::new("normal", "1.0.0").publish(); + Package::new("normal_pm", "1.0.0").publish(); + Package::new("normal_opt", "1.0.0").publish(); + Package::new("dev_dep", "1.0.0").publish(); + Package::new("dev_dep_pm", "1.0.0").publish(); + Package::new("build_dep", "1.0.0").publish(); + Package::new("build_dep_pm", "1.0.0").publish(); + Package::new("build_dep_opt", "1.0.0").publish(); + + Package::new("itarget_normal", "1.0.0").publish(); + Package::new("itarget_normal_pm", "1.0.0").publish(); + Package::new("itarget_dev_dep", "1.0.0").publish(); + Package::new("itarget_dev_dep_pm", "1.0.0").publish(); + Package::new("itarget_build_dep", "1.0.0").publish(); + Package::new("itarget_build_dep_pm", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + normal = "1.0" + normal_pm = "1.0" + normal_opt = { version = "1.0", optional = true } + + [dev-dependencies] + dev_dep = "1.0" + dev_dep_pm = "1.0" + + [build-dependencies] + build_dep = "1.0" + build_dep_pm = "1.0" + build_dep_opt = { version = "1.0", optional = true } + + [target.'cfg(whatever)'.dependencies] + itarget_normal = "1.0" + itarget_normal_pm = "1.0" + + [target.'cfg(whatever)'.dev-dependencies] + itarget_dev_dep = "1.0" + itarget_dev_dep_pm = "1.0" + + [target.'cfg(whatever)'.build-dependencies] + itarget_build_dep = "1.0" + itarget_build_dep_pm = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + let clear = || { + paths::cargo_home().join("registry/cache").rm_rf(); + paths::cargo_home().join("registry/src").rm_rf(); + p.build_dir().rm_rf(); + }; + + // none + // Should be the same as `-Zfeatures=all` + p.cargo("check -Zfeatures=compare") + .masquerade_as_nightly_cargo(&["features=compare"]) + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 14 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`) +[COMPILING] build_dep v1.0.0 +[COMPILING] build_dep_pm v1.0.0 +[CHECKING] normal_pm v1.0.0 +[CHECKING] normal v1.0.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + clear(); + + // New behavior + switch_to_resolver_2(&p); + + // all + p.cargo("check") + .with_stderr_data( + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`) +[COMPILING] build_dep_pm v1.0.0 +[COMPILING] build_dep v1.0.0 +[CHECKING] normal_pm v1.0.0 +[CHECKING] normal v1.0.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + clear(); + + // This disables decouple_dev_deps. + p.cargo("test --no-run") + .with_stderr_data( + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] dev_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] dev_dep v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`) +[COMPILING] build_dep_pm v1.0.0 +[COMPILING] build_dep v1.0.0 +[COMPILING] normal_pm v1.0.0 +[COMPILING] normal v1.0.0 +[COMPILING] dev_dep v1.0.0 +[COMPILING] dev_dep_pm v1.0.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]] + .unordered(), + ) + .run(); + clear(); + + // This disables itarget, but leaves decouple_dev_deps enabled. + p.cargo("tree -e normal --target=all") + .with_stderr_data( + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_normal_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_normal v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_build_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_build_dep v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`) + +"#]] + .unordered(), + ) + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── itarget_normal v1.0.0 +├── itarget_normal_pm v1.0.0 +├── normal v1.0.0 +└── normal_pm v1.0.0 + +"#]]) + .run(); + clear(); + + // This disables itarget and decouple_dev_deps. + p.cargo("tree --target=all") + .with_stderr_data( + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] normal_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] normal v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_normal_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_normal v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_dev_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_dev_dep v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_build_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] itarget_build_dep v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] dev_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] dev_dep v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep_pm v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] build_dep v1.0.0 (registry `dummy-registry`) + +"#]] + .unordered(), + ) + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── itarget_normal v1.0.0 +├── itarget_normal_pm v1.0.0 +├── normal v1.0.0 +└── normal_pm v1.0.0 +[build-dependencies] +├── build_dep v1.0.0 +├── build_dep_pm v1.0.0 +├── itarget_build_dep v1.0.0 +└── itarget_build_dep_pm v1.0.0 +[dev-dependencies] +├── dev_dep v1.0.0 +├── dev_dep_pm v1.0.0 +├── itarget_dev_dep v1.0.0 +└── itarget_dev_dep_pm v1.0.0 + +"#]]) + .run(); + clear(); +} + +#[cargo_test] +fn pm_with_int_shared() { + // This is a somewhat complex scenario of a proc-macro in a workspace with + // an integration test where the proc-macro is used for other things, and + // *everything* is built at once (`--workspace --all-targets + // --all-features`). There was a bug where the UnitFor settings were being + // incorrectly computed based on the order that the graph was traversed. + // + // There are some uncertainties about exactly how proc-macros should behave + // with `--workspace`, see https://github.com/rust-lang/cargo/issues/8312. + // + // This uses a const-eval hack to do compile-time feature checking. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "pm", "shared"] + resolver = "2" + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + pm = { path = "../pm" } + shared = { path = "../shared", features = ["norm-feat"] } + "#, + ) + .file( + "foo/src/lib.rs", + r#" + // foo->shared always has both features set + const _CHECK: [(); 0] = [(); 0-!(shared::FEATS==3) as usize]; + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + shared = { path = "../shared", features = ["host-feat"] } + "#, + ) + .file( + "pm/src/lib.rs", + r#" + // pm->shared always has just host + const _CHECK: [(); 0] = [(); 0-!(shared::FEATS==1) as usize]; + "#, + ) + .file( + "pm/tests/pm_test.rs", + r#" + // integration test gets both set + const _CHECK: [(); 0] = [(); 0-!(shared::FEATS==3) as usize]; + "#, + ) + .file( + "shared/Cargo.toml", + r#" + [package] + name = "shared" + version = "0.1.0" + edition = "2015" + + [features] + norm-feat = [] + host-feat = [] + "#, + ) + .file( + "shared/src/lib.rs", + r#" + pub const FEATS: u32 = { + if cfg!(feature="norm-feat") && cfg!(feature="host-feat") { + 3 + } else if cfg!(feature="norm-feat") { + 2 + } else if cfg!(feature="host-feat") { + 1 + } else { + 0 + } + }; + "#, + ) + .build(); + + p.cargo("build --workspace --all-targets --all-features -v") + .with_stderr_data( + str![[r#" +[COMPILING] shared v0.1.0 ([ROOT]/foo/shared) +[RUNNING] `rustc --crate-name shared [..]--crate-type lib [..]` +[RUNNING] `rustc --crate-name shared [..]--crate-type lib [..]` +[RUNNING] `rustc --crate-name shared [..]--test[..]` +[COMPILING] pm v0.1.0 ([ROOT]/foo/pm) +[RUNNING] `rustc --crate-name pm [..]--crate-type proc-macro[..]` +[RUNNING] `rustc --crate-name pm [..]--test[..]` +[COMPILING] foo v0.1.0 ([ROOT]/foo/foo) +[RUNNING] `rustc --crate-name foo [..]--crate-type lib [..]` +[RUNNING] `rustc --crate-name foo [..]--test[..]` +[RUNNING] `rustc --crate-name pm_test [..]--test[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + // And again, should stay fresh. + p.cargo("build --workspace --all-targets --all-features -v") + .with_stderr_data( + str![[r#" +[FRESH] pm v0.1.0 ([ROOT]/foo/pm) +[FRESH] foo v0.1.0 ([ROOT]/foo/foo) +[FRESH] shared v0.1.0 ([ROOT]/foo/shared) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doc_proc_macro() { + // Checks for a bug when documenting a proc-macro with a dependency. The + // doc unit builder was not carrying the "for host" setting through the + // dependencies, and the `pm-dep` dependency was causing a panic because + // it was looking for target features instead of host features. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [dependencies] + pm = { path = "pm" } + "#, + ) + .file("src/lib.rs", "") + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + pm-dep = { path = "../pm-dep" } + "#, + ) + .file("pm/src/lib.rs", "") + .file("pm-dep/Cargo.toml", &basic_manifest("pm-dep", "0.1.0")) + .file("pm-dep/src/lib.rs", "") + .build(); + + // Unfortunately this cannot check the output because what it prints is + // nondeterministic. Sometimes it says "Compiling pm-dep" and sometimes + // "Checking pm-dep". This is because it is both building it and checking + // it in parallel (building so it can build the proc-macro, and checking + // so rustdoc can load it). + p.cargo("doc").run(); +} + +#[cargo_test] +fn edition_2021_default_2() { + // edition = 2021 defaults to v2 resolver. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .file("src/lib.rs", "") + .publish(); + + Package::new("bar", "1.0.0") + .add_dep( + Dependency::new("common", "1.0") + .target("cfg(whatever)") + .enable_features(&["f1"]), + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + common = "1.0" + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // First without edition. + p.cargo("tree -f") + .arg("{p} feats:{f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) feats: +├── bar v1.0.0 feats: +└── common v1.0.0 feats:f1 + +"#]]) + .run(); + + p.change_file( + "Cargo.toml", + r#" + cargo-features = ["edition2021"] + + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + common = "1.0" + bar = "1.0" + "#, + ); + + // Importantly, this does not include `f1` on `common`. + p.cargo("tree -f") + .arg("{p} feats:{f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) feats: +├── bar v1.0.0 feats: +└── common v1.0.0 feats: + +"#]]) + .run(); +} + +#[cargo_test] +fn all_features_merges_with_features() { + Package::new("dep", "0.1.0") + .feature("feat1", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(feature="feat1")] + pub fn work() { + println!("it works"); + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [features] + a = [] + + [dependencies] + dep = "0.1" + + [[example]] + name = "ex" + required-features = ["a", "dep/feat1"] + "#, + ) + .file( + "examples/ex.rs", + r#" + fn main() { + dep::work(); + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("run --example ex --all-features --features dep/feat1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[COMPILING] dep v0.1.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/examples/ex[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +it works + +"#]]) + .run(); + + switch_to_resolver_2(&p); + + p.cargo("run --example ex --all-features --features dep/feat1") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/examples/ex[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +it works + +"#]]) + .run(); +} + +#[cargo_test] +fn dep_with_optional_host_deps_activated() { + // To prevent regression like rust-lang/cargo#11330 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + serde = { path = "serde", features = ["derive", "build"] } + "#, + ) + .file("src/lib.rs", "") + .file( + "serde/Cargo.toml", + r#" + [package] + name = "serde" + version = "0.1.0" + edition = "2021" + + [dependencies] + serde_derive = { path = "../serde_derive", optional = true } + + [build-dependencies] + serde_build = { path = "../serde_build", optional = true } + + [features] + derive = ["dep:serde_derive"] + build = ["dep:serde_build"] + "#, + ) + .file("serde/src/lib.rs", "") + .file("serde/build.rs", "fn main() {}") + .file( + "serde_derive/Cargo.toml", + r#" + [package] + name = "serde_derive" + version = "0.1.0" + edition = "2021" + + [lib] + proc-macro = true + "#, + ) + .file("serde_derive/src/lib.rs", "") + .file( + "serde_build/Cargo.toml", + &basic_manifest("serde_build", "0.1.0"), + ) + .file("serde_build/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 3 packages to latest compatible versions +[COMPILING] serde_build v0.1.0 ([ROOT]/foo/serde_build) +[COMPILING] serde_derive v0.1.0 ([ROOT]/foo/serde_derive) +[COMPILING] serde v0.1.0 ([ROOT]/foo/serde) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn dont_unify_proc_macro_example_from_dependency() { + // See https://github.com/rust-lang/cargo/issues/13726 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2021" + + [dependencies] + pm_helper = { path = "pm_helper" } + "#, + ) + .file("src/lib.rs", "") + .file( + "pm_helper/Cargo.toml", + r#" + [package] + name = "pm_helper" + + [[example]] + name = "pm" + proc-macro = true + crate-type = ["proc-macro"] + "#, + ) + .file("pm_helper/src/lib.rs", "") + .file("pm_helper/examples/pm.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] pm_helper v0.0.0 ([ROOT]/foo/pm_helper) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features_namespaced.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features_namespaced.rs new file mode 100644 index 000000000..f7315feb8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/features_namespaced.rs @@ -0,0 +1,1369 @@ +//! Tests for namespaced features. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package, RegistryBuilder}; +use cargo_test_support::str; +use cargo_test_support::{project, publish}; + +use super::features2::switch_to_resolver_2; + +#[cargo_test] +fn dependency_with_crate_syntax() { + // Registry dependency uses dep: syntax. + Package::new("baz", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("baz", "1.0").optional(true)) + .feature("feat", &["dep:baz"]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {version="1.0", features=["feat"]} + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] baz v1.0.0 +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn namespaced_invalid_feature() { + // Specifies a feature that doesn't exist. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + bar = ["baz"] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `bar` includes `baz` which is neither a dependency nor another feature + +"#]]) + .run(); +} + +#[cargo_test] +fn namespaced_invalid_dependency() { + // Specifies a dep:name that doesn't exist. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [features] + bar = ["dep:baz"] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `bar` includes `dep:baz`, but `baz` is not listed as a dependency + +"#]]) + .run(); +} + +#[cargo_test] +fn namespaced_non_optional_dependency() { + // Specifies a dep:name for a dependency that is not optional. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [features] + bar = ["dep:baz"] + + [dependencies] + baz = "0.1" + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `bar` includes `dep:baz`, but `baz` is not an optional dependency + A non-optional dependency of the same name is defined; consider adding `optional = true` to its definition. + +"#]]) + .run(); +} + +#[cargo_test] +fn namespaced_implicit_feature() { + // Backwards-compatible with old syntax. + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [features] + bar = ["baz"] + + [dependencies] + baz = { version = "0.1", optional = true } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check --features baz") + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`) +[CHECKING] baz v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn namespaced_shadowed_dep() { + // An optional dependency is not listed in the features table, and its + // implicit feature is overridden. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [features] + baz = [] + + [dependencies] + baz = { version = "0.1", optional = true } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + optional dependency `baz` is not included in any feature + Make sure that `dep:baz` is included in one of features in the [features] table. + +"#]]) + .run(); +} + +#[cargo_test] +fn namespaced_shadowed_non_optional() { + // Able to specify a feature with the same name as a required dependency. + Package::new("baz", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [features] + baz = [] + + [dependencies] + baz = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn namespaced_implicit_non_optional() { + // Includes a non-optional dependency in [features] table. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [features] + bar = ["baz"] + + [dependencies] + baz = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `bar` includes `baz`, but `baz` is not an optional dependency + A non-optional dependency of the same name is defined; consider adding `optional = true` to its definition. + +"#]]) + .run(); +} + +#[cargo_test] +fn namespaced_same_name() { + // Explicitly listing an optional dependency in the [features] table. + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [features] + baz = ["dep:baz"] + + [dependencies] + baz = { version = "0.1", optional = true } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(feature="baz") { println!("baz"); } + } + "#, + ) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data("") + .run(); + + p.cargo("run --features baz") + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`) +[COMPILING] baz v0.1.0 +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +baz + +"#]]) + .run(); +} + +#[cargo_test] +fn no_implicit_feature() { + // Using `dep:` will not create an implicit feature. + Package::new("regex", "1.0.0").publish(); + Package::new("lazy_static", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + regex = { version = "1.0", optional = true } + lazy_static = { version = "1.0", optional = true } + + [features] + regex = ["dep:regex", "dep:lazy_static"] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(feature = "regex") { println!("regex"); } + #[allow(unexpected_cfgs)] + if cfg!(feature = "lazy_static") { println!("lazy_static"); } + } + "#, + ) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data("") + .run(); + + p.cargo("run --features regex") + .with_stderr_data( + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] regex v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] lazy_static v1.0.0 (registry `dummy-registry`) +[COMPILING] regex v1.0.0 +[COMPILING] lazy_static v1.0.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]] + .unordered(), + ) + .with_stdout_data(str![[r#" +regex + +"#]]) + .run(); + + p.cargo("run --features lazy_static") + .with_stderr_data(str![[r#" +[ERROR] Package `foo v0.1.0 ([ROOT]/foo)` does not have feature `lazy_static`. It has an optional dependency with that name, but that dependency uses the "dep:" syntax in the features table, so it does not have an implicit feature with that name. +Dependency `lazy_static` would be enabled by these features: + - `regex` + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn crate_syntax_bad_name() { + // "dep:bar" = [] + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version="1.0", optional=true } + + [features] + "dep:bar" = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check --features dep:bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] feature named `dep:bar` is not allowed to start with `dep:` + --> Cargo.toml:11:17 + | +11 | "dep:bar" = [] + | ^^^^^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn crate_syntax_in_dep() { + // features = ["dep:baz"] + Package::new("baz", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("baz", "1.0").optional(true)) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", features = ["dep:baz"] } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `dep:baz` in dependency `bar` is not allowed to use explicit `dep:` syntax + If you want to enable an optional dependency, specify the name of the optional dependency without the `dep:` prefix, or specify a feature from the dependency's `[features]` table that enables the optional dependency. + +"#]]) + .run(); +} + +#[cargo_test] +fn crate_syntax_cli() { + // --features dep:bar + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional=true } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check --features dep:bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] feature `dep:bar` is not allowed to use explicit `dep:` syntax + +"#]]) + .run(); + + switch_to_resolver_2(&p); + p.cargo("check --features dep:bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] feature `dep:bar` is not allowed to use explicit `dep:` syntax + +"#]]) + .run(); +} + +#[cargo_test] +fn crate_required_features() { + // required-features = ["dep:bar"] + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional=true } + + [[bin]] + name = "foo" + required-features = ["dep:bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ERROR] invalid feature `dep:bar` in required-features of target `foo`: `dep:` prefixed feature values are not allowed in required-features + +"#]]) + .run(); +} + +#[cargo_test] +fn json_exposed() { + // Checks that the implicit dep: values are exposed in JSON. + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional=true } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("metadata --no-deps") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": "{...}", + "description": null, + "documentation": null, + "edition": "2015", + "features": { + "bar": [ + "dep:bar" + ] + }, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": "{...}", + "version": "0.1.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} + +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn crate_feature_with_explicit() { + // crate_name/feat_name syntax where crate_name already has a feature defined. + // NOTE: I don't know if this is actually ideal behavior. + Package::new("bar", "1.0.0") + .feature("bar_feat", &[]) + .file( + "src/lib.rs", + r#" + #[cfg(not(feature="bar_feat"))] + compile_error!("bar_feat is not enabled"); + "#, + ) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version="1.0", optional = true } + + [features] + f1 = ["bar/bar_feat"] + bar = ["dep:bar", "f2"] + f2 = [] + "#, + ) + .file( + "src/lib.rs", + r#" + #[cfg(not(feature="bar"))] + compile_error!("bar should be enabled"); + + #[cfg(not(feature="f2"))] + compile_error!("f2 should be enabled"); + "#, + ) + .build(); + + p.cargo("check --features f1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn optional_explicit_without_crate() { + // "feat" syntax when there is no implicit "feat" feature because it is + // explicitly listed elsewhere. + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional = true } + + [features] + feat1 = ["dep:bar"] + feat2 = ["bar"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `feat2` includes `bar`, but `bar` is an optional dependency without an implicit feature + Use `dep:bar` to enable the dependency. + +"#]]) + .run(); +} + +#[cargo_test] +fn tree() { + Package::new("baz", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("baz", "1.0").optional(true)) + .feature("feat1", &["dep:baz"]) + .feature("feat2", &[]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", features = ["feat1"], optional=true } + + [features] + a = ["bar/feat2"] + bar = ["dep:bar"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -e features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree -e features --features a") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── bar feature "default" +│ └── bar v1.0.0 +│ └── baz feature "default" +│ └── baz v1.0.0 +└── bar feature "feat1" + └── bar v1.0.0 (*) + +"#]]) + .run(); + + p.cargo("tree -e features --features a -i bar") + .with_stdout_data(str![[r#" +bar v1.0.0 +├── bar feature "default" +│ └── foo v0.1.0 ([ROOT]/foo) +│ ├── foo feature "a" (command-line) +│ ├── foo feature "bar" +│ │ └── foo feature "a" (command-line) +│ └── foo feature "default" (command-line) +├── bar feature "feat1" +│ └── foo v0.1.0 ([ROOT]/foo) (*) +└── bar feature "feat2" + └── foo feature "a" (command-line) + +"#]]) + .run(); + + p.cargo("tree -e features --features bar") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── bar feature "default" +│ └── bar v1.0.0 +│ └── baz feature "default" +│ └── baz v1.0.0 +└── bar feature "feat1" + └── bar v1.0.0 (*) + +"#]]) + .run(); + + p.cargo("tree -e features --features bar -i bar") + .with_stdout_data(str![[r#" +bar v1.0.0 +├── bar feature "default" +│ └── foo v0.1.0 ([ROOT]/foo) +│ ├── foo feature "bar" (command-line) +│ └── foo feature "default" (command-line) +└── bar feature "feat1" + └── foo v0.1.0 ([ROOT]/foo) (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn tree_no_implicit() { + // tree without an implicit feature + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional=true } + + [features] + a = ["dep:bar"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -e features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree -e features --all-features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar feature "default" + └── bar v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -e features -i bar --all-features") + .with_stdout_data(str![[r#" +bar v1.0.0 +└── bar feature "default" + └── foo v0.1.0 ([ROOT]/foo) + ├── foo feature "a" (command-line) + └── foo feature "default" (command-line) + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_no_implicit() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + // Does not include implicit features or dep: syntax on publish. + Package::new("opt-dep1", "1.0.0").publish(); + Package::new("opt-dep2", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "MIT" + homepage = "https://example.com/" + + [dependencies] + opt-dep1 = { version = "1.0", optional = true } + opt-dep2 = { version = "1.0", optional = true } + + [features] + feat = ["opt-dep1"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +[UPLOADED] foo v0.1.0 to registry `crates-io` +[NOTE] waiting for `foo v0.1.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.1.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "opt-dep1", + "optional": true, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "opt-dep2", + "optional": true, + "target": null, + "version_req": "^1.0" + } + ], + "description": "foo", + "documentation": null, + "features": { + "feat": ["opt-dep1"] + }, + "homepage": "https://example.com/", + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.1.0" + } + "#, + "foo-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.1.0" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "https://example.com/" +readme = false +license = "MIT" + +[features] +feat = ["opt-dep1"] + +[lib] +name = "foo" +path = "src/lib.rs" + +[dependencies.opt-dep1] +version = "1.0" +optional = true + +[dependencies.opt-dep2] +version = "1.0" +optional = true + +"##]], + )], + ); +} + +#[cargo_test] +fn publish() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + // Publish behavior with explicit dep: syntax. + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "MIT" + homepage = "https://example.com/" + + [dependencies] + bar = { version = "1.0", optional = true } + + [features] + feat1 = [] + feat2 = ["dep:bar"] + feat3 = ["feat2"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.1.0 ([ROOT]/foo) +[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +[UPLOADED] foo v0.1.0 to registry `crates-io` +[NOTE] waiting for `foo v0.1.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.1.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "bar", + "optional": true, + "target": null, + "version_req": "^1.0" + } + ], + "description": "foo", + "documentation": null, + "features": { + "feat1": [], + "feat2": ["dep:bar"], + "feat3": ["feat2"] + }, + "homepage": "https://example.com/", + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.1.0" + } + "#, + "foo-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.1.0" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "https://example.com/" +readme = false +license = "MIT" + +[features] +feat1 = [] +feat2 = ["dep:bar"] +feat3 = ["feat2"] + +[lib] +name = "foo" +path = "src/lib.rs" + +[dependencies.bar] +version = "1.0" +optional = true + +"##]], + )], + ); +} + +#[cargo_test] +fn namespaced_feature_together() { + // Check for an error when `dep:` is used with `/` + Package::new("bar", "1.0.0") + .feature("bar-feat", &[]) + .publish(); + + // Non-optional shouldn't have extra err. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + + [features] + f1 = ["dep:bar/bar-feat"] + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `f1` includes `dep:bar/bar-feat` with both `dep:` and `/` + To fix this, remove the `dep:` prefix. + +"#]]) + .run(); + + // Weak dependency shouldn't have extra err. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {version = "1.0", optional = true } + + [features] + f1 = ["dep:bar?/bar-feat"] + "#, + ); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `f1` includes `dep:bar?/bar-feat` with both `dep:` and `/` + To fix this, remove the `dep:` prefix. + +"#]]) + .run(); + + // If dep: is already specified, shouldn't have extra err. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {version = "1.0", optional = true } + + [features] + f1 = ["dep:bar", "dep:bar/bar-feat"] + "#, + ); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `f1` includes `dep:bar/bar-feat` with both `dep:` and `/` + To fix this, remove the `dep:` prefix. + +"#]]) + .run(); + + // Only when the other 3 cases aren't true should it give some extra help. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {version = "1.0", optional = true } + + [features] + f1 = ["dep:bar/bar-feat"] + "#, + ); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `f1` includes `dep:bar/bar-feat` with both `dep:` and `/` + To fix this, remove the `dep:` prefix. + If the intent is to avoid creating an implicit feature `bar` for an optional dependency, then consider replacing this with two values: + "dep:bar", "bar/bar-feat" + +"#]]) + .run(); +} + +#[cargo_test] +fn dep_feature_when_hidden() { + // Checks for behavior with dep:bar and bar/feat syntax when there is no + // `bar` feature. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar", optional = true } + + [features] + f1 = ["dep:bar"] + f2 = ["bar/bar_feat"] + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [features] + bar_feat = [] + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("tree -f") + .arg("{p} features={f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) features= + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); + + p.cargo("tree -F f1 -f") + .arg("{p} features={f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) features=f1 +└── bar v0.1.0 ([ROOT]/foo/bar) features= + +"#]]) + .with_stderr_data("") + .run(); + + p.cargo("tree -F f2 -f") + .arg("{p} features={f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) features=f2 +└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat + +"#]]) + .with_stderr_data("") + .run(); + + p.cargo("tree --all-features -f") + .arg("{p} features={f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) features=f1,f2 +└── bar v0.1.0 ([ROOT]/foo/bar) features=bar_feat + +"#]]) + .with_stderr_data("") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fetch.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fetch.rs new file mode 100644 index 000000000..ba5c3a136 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fetch.rs @@ -0,0 +1,146 @@ +//! Tests for the `cargo fetch` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::rustc_host; +use cargo_test_support::{basic_manifest, cross_compile, project, str}; + +#[cargo_test] +fn no_deps() { + let p = project() + .file("src/main.rs", "mod a; fn main() {}") + .file("src/a.rs", "") + .build(); + + p.cargo("fetch").with_stderr_data("").run(); +} + +#[cargo_test] +fn fetch_all_platform_dependencies_when_no_target_is_given() { + if cross_compile::disabled() { + return; + } + + Package::new("d1", "1.2.3") + .file("Cargo.toml", &basic_manifest("d1", "1.2.3")) + .file("src/lib.rs", "") + .publish(); + + Package::new("d2", "0.1.2") + .file("Cargo.toml", &basic_manifest("d2", "0.1.2")) + .file("src/lib.rs", "") + .publish(); + + let target = cross_compile::alternate(); + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.{host}.dependencies] + d1 = "1.2.3" + + [target.{target}.dependencies] + d2 = "0.1.2" + "#, + host = host, + target = target + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch") + .with_stderr_data(str![[r#" +... +[DOWNLOADED] d1 v1.2.3 (registry `dummy-registry`) +[DOWNLOADED] d2 v0.1.2 (registry `dummy-registry`) +... +"#]]) + .run(); +} + +#[cargo_test] +fn fetch_platform_specific_dependencies() { + if cross_compile::disabled() { + return; + } + + Package::new("d1", "1.2.3") + .file("Cargo.toml", &basic_manifest("d1", "1.2.3")) + .file("src/lib.rs", "") + .publish(); + + Package::new("d2", "0.1.2") + .file("Cargo.toml", &basic_manifest("d2", "0.1.2")) + .file("src/lib.rs", "") + .publish(); + + let target = cross_compile::alternate(); + let host = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.{host}.dependencies] + d1 = "1.2.3" + + [target.{target}.dependencies] + d2 = "0.1.2" + "#, + host = host, + target = target + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch --target") + .arg(&host) + .with_stderr_contains("[DOWNLOADED] d1 v1.2.3 [..]") + .with_stderr_does_not_contain("[DOWNLOADED] d2 v0.1.2 [..]") + .run(); + + p.cargo("fetch --target") + .arg(&target) + .with_stderr_contains("[DOWNLOADED] d2 v0.1.2[..]") + .with_stderr_does_not_contain("[DOWNLOADED] d1 v1.2.3 [..]") + .run(); +} + +#[cargo_test] +fn fetch_warning() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + misspelled = "wut" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_stderr_data(str![[r#" +[WARNING] unused manifest key: package.misspelled + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix.rs new file mode 100644 index 000000000..7d9c4610c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix.rs @@ -0,0 +1,2869 @@ +//! Tests for the `cargo fix` command. + +use cargo::core::Edition; +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::git::{self, init}; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::str; +use cargo_test_support::tools; +use cargo_test_support::{basic_manifest, is_nightly, project}; + +#[cargo_test] +fn do_not_fix_broken_builds() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() { + let mut x = 3; + let _ = x; + } + + pub fn foo2() { + let _x: u32 = "a"; + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] could not compile `foo` (lib) due to 1 previous error; 1 warning emitted +... +"#]]) + .run(); + assert!(p.read_file("src/lib.rs").contains("let mut x = 3;")); +} + +#[cargo_test] +fn fix_broken_if_requested() { + let p = project() + .file( + "src/lib.rs", + r#" + fn foo(a: &u32) -> u32 { a + 1 } + pub fn bar() { + foo(1); + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs --broken-code") + .env("__CARGO_FIX_YOLO", "1") + .run(); +} + +#[cargo_test] +fn fix_path_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = 'bar' } + + [workspace] + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + + pub fn foo() -> u32 { + let mut x = 3; + x + } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file( + "bar/src/lib.rs", + r#" + pub fn foo() -> u32 { + let mut x = 3; + x + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs -p foo -p bar") + .env("__CARGO_FIX_YOLO", "1") + .with_stdout_data("") + .with_stderr_data( + str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FIXED] bar/src/lib.rs (1 fix) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn do_not_fix_non_relevant_deps() { + let p = project() + .no_manifest() + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = '../bar' } + + [workspace] + "#, + ) + .file("foo/src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file( + "bar/src/lib.rs", + r#" + pub fn foo() -> u32 { + let mut x = 3; + x + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .cwd("foo") + .run(); + + assert!(p.read_file("bar/src/lib.rs").contains("mut")); +} + +#[cargo_test] +fn prepare_for_2018() { + let p = project() + .file( + "src/lib.rs", + r#" + #![allow(unused)] + + mod foo { + pub const FOO: &str = "fooo"; + } + + mod bar { + use ::foo::FOO; + } + + fn main() { + let x = ::foo::FOO; + } + "#, + ) + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2015 edition to 2018 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2015 edition to 2018 +[FIXED] src/lib.rs (2 fixes) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + println!("{}", p.read_file("src/lib.rs")); + assert!(p.read_file("src/lib.rs").contains("use crate::foo::FOO;")); + assert!(p + .read_file("src/lib.rs") + .contains("let x = crate::foo::FOO;")); +} + +#[cargo_test] +fn local_paths() { + let p = project() + .file( + "src/lib.rs", + r#" + use test::foo; + + mod test { + pub fn foo() {} + } + + pub fn f() { + foo(); + } + "#, + ) + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2015 edition to 2018 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2015 edition to 2018 +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + println!("{}", p.read_file("src/lib.rs")); + assert!(p.read_file("src/lib.rs").contains("use crate::test::foo;")); +} + +#[cargo_test] +fn upgrade_extern_crate() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = '2018' + + [workspace] + + [dependencies] + bar = { path = 'bar' } + "#, + ) + .file( + "src/lib.rs", + r#" + #![warn(rust_2018_idioms)] + extern crate bar; + + use bar::bar; + + pub fn foo() { + ::bar::bar(); + bar(); + } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + println!("{}", p.read_file("src/lib.rs")); + assert!(!p.read_file("src/lib.rs").contains("extern crate")); +} + +#[cargo_test] +fn specify_rustflags() { + let p = project() + .file( + "src/lib.rs", + r#" + #![allow(unused)] + + mod foo { + pub const FOO: &str = "fooo"; + } + + fn main() { + let x = ::foo::FOO; + } + "#, + ) + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2015 edition to 2018 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2015 edition to 2018 +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn no_changes_necessary() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("fix --allow-no-vcs") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn fixes_extra_mut() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { + let mut x = 3; + x + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn fixes_two_missing_ampersands() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { + let mut x = 3; + let mut y = 3; + x + y + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FIXED] src/lib.rs (2 fixes) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn tricky() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { + let mut x = 3; let mut y = 3; + x + y + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FIXED] src/lib.rs (2 fixes) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn preserve_line_endings() { + let p = project() + .file( + "src/lib.rs", + "fn add(a: &u32) -> u32 { a + 1 }\r\n\ + pub fn foo() -> u32 { let mut x = 3; add(&x) }\r\n\ + ", + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .run(); + assert!(p.read_file("src/lib.rs").contains("\r\n")); +} + +#[cargo_test] +fn fix_deny_warnings() { + let p = project() + .file( + "src/lib.rs", + "#![deny(warnings)] + pub fn foo() { let mut x = 3; let _ = x; } + ", + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .run(); +} + +#[cargo_test] +fn fix_deny_warnings_but_not_others() { + let p = project() + .file( + "src/lib.rs", + " + #![deny(unused_mut)] + + pub fn foo() -> u32 { + let mut x = 3; + x + } + + pub fn bar() { + #[allow(unused_mut)] + let mut _y = 4; + } + ", + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .run(); + assert!(!p.read_file("src/lib.rs").contains("let mut x = 3;")); + assert!(p.read_file("src/lib.rs").contains("let mut _y = 4;")); +} + +#[cargo_test] +fn fix_two_files() { + let p = project() + .file( + "src/lib.rs", + " + pub mod bar; + + pub fn foo() -> u32 { + let mut x = 3; + x + } + ", + ) + .file( + "src/bar.rs", + " + pub fn foo() -> u32 { + let mut x = 3; + x + } + + ", + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stderr_data( + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FIXED] src/bar.rs (1 fix) +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + assert!(!p.read_file("src/lib.rs").contains("let mut x = 3;")); + assert!(!p.read_file("src/bar.rs").contains("let mut x = 3;")); +} + +#[cargo_test] +fn fixes_missing_ampersand() { + let p = project() + .file("src/main.rs", "fn main() { let mut x = 3; let _ = x; }") + .file( + "src/lib.rs", + r#" + pub fn foo() { let mut x = 3; let _ = x; } + + #[test] + pub fn foo2() { let mut x = 3; let _ = x; } + "#, + ) + .file( + "tests/a.rs", + r#" + #[test] + pub fn foo() { let mut x = 3; let _ = x; } + "#, + ) + .file("examples/foo.rs", "fn main() { let mut x = 3; let _ = x; }") + .file("build.rs", "fn main() { let mut x = 3; let _ = x; }") + .build(); + + p.cargo("fix --all-targets --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stdout_data("") + // Don't assert number of fixes for `src/lib.rs`, as we don't know if we're + // fixing it once or twice! We run this all concurrently, and if we + // compile (and fix) in `--test` mode first, we get two fixes. Otherwise + // we'll fix one non-test thing, and then fix another one later in + // test mode. + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FIXED] build.rs (1 fix) +[FIXED] src/lib.rs ([..]fix[..]) +[FIXED] src/main.rs (1 fix) +[FIXED] examples/foo.rs (1 fix) +[FIXED] tests/a.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +... +"#]] + .unordered(), + ) + .run(); + p.cargo("check").run(); + p.cargo("test").run(); +} + +#[cargo_test] +fn fix_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [features] + bar = [] + + [workspace] + "#, + ) + .file( + "src/lib.rs", + r#" + #[cfg(feature = "bar")] + pub fn foo() -> u32 { let mut x = 3; x } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs").run(); + p.cargo("check").run(); + p.cargo("fix --features bar --allow-no-vcs").run(); + p.cargo("check --features bar").run(); +} + +#[cargo_test] +fn shows_warnings() { + let p = project() + .file( + "src/lib.rs", + "#[deprecated] fn bar() {} pub fn foo() { let _ = bar(); }", + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .with_stderr_data(str![[r#" +... +[WARNING] use of deprecated function `bar` +... +"#]]) + .run(); +} + +#[cargo_test] +fn warns_if_no_vcs_detected() { + let p = project().file("src/lib.rs", "pub fn foo() {}").build(); + + p.cargo("fix") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no VCS found for this package and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-no-vcs` + +"#]]) + .run(); + p.cargo("fix --allow-no-vcs").run(); +} + +#[cargo_test] +fn warns_about_dirty_working_directory() { + let p = git::new("foo", |p| p.file("src/lib.rs", "pub fn foo() {}")); + + p.change_file("src/lib.rs", ""); + + p.cargo("fix") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, or commit the changes to these files: + + * src/lib.rs (dirty) + + + +"#]]) + .run(); + p.cargo("fix --allow-dirty").run(); +} + +#[cargo_test] +fn warns_about_staged_working_directory() { + let (p, repo) = git::new_repo("foo", |p| p.file("src/lib.rs", "pub fn foo() {}")); + + p.change_file("src/lib.rs", "pub fn bar() {}"); + git::add(&repo); + + p.cargo("fix") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, or commit the changes to these files: + + * src/lib.rs (staged) + + + +"#]]) + .run(); + p.cargo("fix --allow-staged").run(); +} + +#[cargo_test] +fn errors_about_untracked_files() { + let mut git_project = project().at("foo"); + git_project = git_project.file("src/lib.rs", "pub fn foo() {}"); + let p = git_project.build(); + let _ = init(&p.root()); + + p.cargo("fix") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the working directory of this package has uncommitted changes, and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-dirty`, or commit the changes to these files: + + * Cargo.toml (dirty) + * src/ (dirty) + + + +"#]]) + .run(); + p.cargo("fix --allow-dirty").run(); +} + +#[cargo_test] +fn does_not_warn_about_clean_working_directory() { + let p = git::new("foo", |p| p.file("src/lib.rs", "pub fn foo() {}")); + p.cargo("fix").run(); +} + +#[cargo_test] +fn does_not_warn_about_dirty_ignored_files() { + let p = git::new("foo", |p| { + p.file("src/lib.rs", "pub fn foo() {}") + .file(".gitignore", "bar\n") + }); + + p.change_file("bar", ""); + + p.cargo("fix").run(); +} + +#[cargo_test] +fn fix_all_targets_by_default() { + let p = project() + .file("src/lib.rs", "pub fn foo() { let mut x = 3; let _ = x; }") + .file("tests/foo.rs", "pub fn foo() { let mut x = 3; let _ = x; }") + .build(); + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .run(); + assert!(!p.read_file("src/lib.rs").contains("let mut x")); + assert!(!p.read_file("tests/foo.rs").contains("let mut x")); +} + +#[cargo_test] +fn prepare_for_unstable() { + // During the period where a new edition is coming up, but not yet stable, + // this test will verify that it cannot be migrated to on stable. If there + // is no next edition, it does nothing. + let next = match Edition::LATEST_UNSTABLE { + Some(next) => next, + None => { + eprintln!("Next edition is currently not available, skipping test."); + return; + } + }; + let latest_stable = Edition::LATEST_STABLE; + let prev = latest_stable.previous().unwrap(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "{}" + "#, + latest_stable + ), + ) + .file("src/lib.rs", "") + .build(); + + // -j1 to make the error more deterministic (otherwise there can be + // multiple errors since they run in parallel). + p.cargo("fix --edition --allow-no-vcs -j1") + .with_stderr_data(&format!("\ +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[WARNING] `src/lib.rs` is on the latest edition, but trying to migrate to edition {next}. +Edition {next} is unstable and not allowed in this release, consider trying the nightly release channel. + +If you are trying to migrate from the previous edition ({prev}), the +process requires following these steps: + +1. Start with `edition = \"{prev}\"` in `Cargo.toml` +2. Run `cargo fix --edition` +3. Modify `Cargo.toml` to set `edition = \"{latest_stable}\"` +4. Run `cargo build` or `cargo test` to verify the fixes worked + +More details may be found at +https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html + +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", next=next, latest_stable=latest_stable, prev=prev)) + .run(); + + if !is_nightly() { + // The rest of this test is fundamentally always nightly. + return; + } + + p.cargo("fix --edition --allow-no-vcs") + .masquerade_as_nightly_cargo(&["always_nightly"]) + .with_stderr_data(&format!( + "\ +[MIGRATING] Cargo.toml from {latest_stable} edition to {next} +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from {latest_stable} edition to {next} +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + latest_stable = latest_stable, + next = next, + )) + .run(); +} + +#[cargo_test] +fn prepare_for_latest_stable() { + // This is the stable counterpart of prepare_for_unstable. + let latest_stable = Edition::LATEST_STABLE; + let previous = latest_stable.previous().unwrap(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = '{}' + "#, + previous + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(&format!( + "\ +[MIGRATING] Cargo.toml from {previous} edition to {latest_stable} +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from {previous} edition to {latest_stable} +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + )) + .run(); +} + +#[cargo_test(nightly, reason = "fundamentally always nightly")] +fn prepare_for_already_on_latest_unstable() { + // During the period where a new edition is coming up, but not yet stable, + // this test will check what happens if you are already on the latest. If + // there is no next edition, it does nothing. + let next_edition = match Edition::LATEST_UNSTABLE { + Some(next) => next, + None => { + eprintln!("Next edition is currently not available, skipping test."); + return; + } + }; + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + cargo-features = ["edition{}"] + + [package] + name = 'foo' + version = '0.1.0' + edition = '{}' + "#, + next_edition, next_edition + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .masquerade_as_nightly_cargo(&["always_nightly"]) + .with_stderr_data(&format!( + "\ +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[WARNING] `src/lib.rs` is already on the latest edition ({next_edition}), unable to migrate further +... +", + next_edition = next_edition + )) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn prepare_for_already_on_latest_stable() { + // Stable counterpart of prepare_for_already_on_latest_unstable. + if Edition::LATEST_UNSTABLE.is_some() { + eprintln!("This test cannot run while the latest edition is unstable, skipping."); + return; + } + let latest_stable = Edition::LATEST_STABLE; + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = '{}' + "#, + latest_stable + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_contains("[CHECKING] foo [..]") + .with_stderr_contains(&format!( + "\ +[WARNING] `src/lib.rs` is already on the latest edition ({latest_stable}), unable to migrate further +", + latest_stable = latest_stable + )) + .run(); +} + +#[cargo_test] +fn fix_overlapping() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() {} + pub struct A; + + pub mod bar { + pub fn baz() { + ::foo::<::A>(); + } + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs --edition --lib") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2015 edition to 2018 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2015 edition to 2018 +[FIXED] src/lib.rs (2 fixes) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let contents = p.read_file("src/lib.rs"); + println!("{}", contents); + assert!(contents.contains("crate::foo::()")); +} + +#[cargo_test] +fn fix_idioms() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = '2018' + "#, + ) + .file( + "src/lib.rs", + r#" + use std::any::Any; + pub fn foo() { + let _x: Box = Box::new(3); + } + "#, + ) + .build(); + + p.cargo("fix --edition-idioms --allow-no-vcs") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(p.read_file("src/lib.rs").contains("Box")); +} + +#[cargo_test] +fn idioms_2015_ok() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("fix --edition-idioms --allow-no-vcs").run(); +} + +#[cargo_test] +fn shows_warnings_on_second_run_without_changes() { + let p = project() + .file( + "src/lib.rs", + r#" + #[deprecated] + fn bar() {} + + pub fn foo() { + let _ = bar(); + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .with_stderr_data(str![[r#" +... +[WARNING] use of deprecated function `bar` +... +"#]]) + .run(); + + p.cargo("fix --allow-no-vcs") + .with_stderr_data(str![[r#" +... +[WARNING] use of deprecated function `bar` +... +"#]]) + .run(); +} + +#[cargo_test] +fn shows_warnings_on_second_run_without_changes_on_multiple_targets() { + let p = project() + .file( + "src/lib.rs", + r#" + #[deprecated] + fn bar() {} + + pub fn foo() { + let _ = bar(); + } + "#, + ) + .file( + "src/main.rs", + r#" + #[deprecated] + fn bar() {} + + fn main() { + let _ = bar(); + } + "#, + ) + .file( + "tests/foo.rs", + r#" + #[deprecated] + fn bar() {} + + #[test] + fn foo_test() { + let _ = bar(); + } + "#, + ) + .file( + "tests/bar.rs", + r#" + #[deprecated] + fn bar() {} + + #[test] + fn foo_test() { + let _ = bar(); + } + "#, + ) + .file( + "examples/fooxample.rs", + r#" + #[deprecated] + fn bar() {} + + fn main() { + let _ = bar(); + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs --all-targets") + .with_stderr_data( + str![[r#" +... + --> src/lib.rs:6:29 +... + --> src/main.rs:6:29 +... + --> examples/fooxample.rs:6:29 +... + --> tests/foo.rs:7:29 +... + --> tests/bar.rs:7:29 +... + +"#]] + .unordered(), + ) + .run(); + + p.cargo("fix --allow-no-vcs --all-targets") + .with_stderr_data( + str![[r#" +... + --> src/lib.rs:6:29 +... + --> src/main.rs:6:29 +... + --> examples/fooxample.rs:6:29 +... + --> tests/bar.rs:7:29 +... + --> tests/foo.rs:7:29 +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doesnt_rebuild_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = 'bar' } + + [workspace] + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("fix --allow-no-vcs -p foo") + .env("__CARGO_FIX_YOLO", "1") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("fix --allow-no-vcs -p foo") + .env("__CARGO_FIX_YOLO", "1") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn does_not_crash_with_rustc_wrapper() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --allow-no-vcs") + .env("RUSTC_WRAPPER", tools::echo_wrapper()) + .run(); + p.build_dir().rm_rf(); + p.cargo("fix --allow-no-vcs --verbose") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .run(); +} + +#[cargo_test] +fn uses_workspace_wrapper_and_primary_wrapper_override() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --allow-no-vcs --verbose") + .env("RUSTC_WORKSPACE_WRAPPER", tools::echo_wrapper()) + .with_stderr_data(str![[r#" +... +WRAPPER CALLED: rustc src/lib.rs --crate-name foo [..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn only_warn_for_relevant_crates() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + a = { path = 'a' } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "a/src/lib.rs", + " + pub fn foo() {} + pub mod bar { + use foo; + pub fn baz() { foo() } + } + ", + ) + .build(); + + p.cargo("fix --allow-no-vcs --edition") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2015 edition to 2018 +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2015 edition to 2018 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fix_to_broken_code() { + let p = project() + .file( + "foo/Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = "2015" + [workspace] + "#, + ) + .file( + "foo/src/main.rs", + r#" + use std::env; + use std::fs; + use std::io::Write; + use std::path::{Path, PathBuf}; + use std::process::{self, Command}; + + fn main() { + // Ignore calls to things like --print=file-names and compiling build.rs. + // Also compatible for rustc invocations with `@path` argfile. + let is_lib_rs = env::args_os() + .map(PathBuf::from) + .flat_map(|p| if let Some(p) = p.to_str().unwrap_or_default().strip_prefix("@") { + fs::read_to_string(p).unwrap().lines().map(PathBuf::from).collect() + } else { + vec![p] + }) + .any(|l| l == Path::new("src/lib.rs")); + if is_lib_rs { + let path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let path = path.join("foo"); + if path.exists() { + panic!() + } else { + fs::File::create(&path).unwrap(); + } + } + + let status = Command::new("rustc") + .args(env::args().skip(1)) + .status() + .expect("failed to run rustc"); + process::exit(status.code().unwrap_or(2)); + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = 'bar' + version = '0.1.0' + edition = "2015" + [workspace] + "#, + ) + .file("bar/build.rs", "fn main() {}") + .file("bar/src/lib.rs", "pub fn foo() { let mut x = 3; let _ = x; }") + .build(); + + // Build our rustc shim + p.cargo("build").cwd("foo").run(); + + // Attempt to fix code, but our shim will always fail the second compile + p.cargo("fix --allow-no-vcs --broken-code") + .cwd("bar") + .env("RUSTC", p.root().join("foo/target/debug/foo")) + .with_status(101) + .with_stderr_data(str![[r#" +... +[WARNING] failed to automatically apply fixes suggested by rustc to crate `bar` +... +"#]]) + .run(); + + assert_e2e().eq( + p.read_file("bar/src/lib.rs"), + str!["pub fn foo() { let x = 3; let _ = x; }"], + ); +} + +#[cargo_test] +fn fix_with_common() { + let p = project() + .file("src/lib.rs", "") + .file( + "tests/t1.rs", + "mod common; #[test] fn t1() { common::try(); }", + ) + .file( + "tests/t2.rs", + "mod common; #[test] fn t2() { common::try(); }", + ) + .file("tests/common/mod.rs", "pub fn try() {}") + .build(); + + p.cargo("fix --edition --allow-no-vcs").run(); + + assert_e2e().eq( + p.read_file("tests/common/mod.rs"), + str!["pub fn r#try() {}"], + ); +} + +#[cargo_test] +fn fix_in_existing_repo_weird_ignore() { + // Check that ignore doesn't ignore the repo itself. + let p = git::new("foo", |project| { + project + .file("src/lib.rs", "") + .file(".gitignore", "foo\ninner\nCargo.lock\ntarget\n") + .file("inner/file", "") + }); + + p.cargo("fix").run(); + // This is questionable about whether it is the right behavior. It should + // probably be checking if any source file for the current project is + // ignored. + p.cargo("fix") + .cwd("inner") + .with_stderr_data(str![[r#" +[ERROR] no VCS found for this package and `cargo fix` can potentially perform destructive changes; if you'd like to suppress this error pass `--allow-no-vcs` + +"#]]) + .with_status(101) + .run(); + p.cargo("fix").cwd("src").run(); +} + +#[cargo_test] +fn fix_color_message() { + // Check that color appears in diagnostics. + let p = project() + .file("src/lib.rs", "std::compile_error!{\"color test\"}") + .build(); + + p.cargo("fix --allow-no-vcs --color=always") + .with_stderr_data( + "\ +... +[..]\x1b[[..] +... +", + ) + .with_status(101) + .run(); + + p.cargo("fix --allow-no-vcs --color=never") + .with_stderr_data(str![[r#" +... +[ERROR] color test +... +"#]]) + .with_stderr_does_not_contain("[..]\x1b[[..]") + .with_status(101) + .run(); +} + +#[cargo_test] +fn edition_v2_resolver_report() { + // Show a report if the V2 resolver shows differences. + Package::new("common", "1.0.0") + .feature("f1", &[]) + .feature("dev-feat", &[]) + .add_dep(Dependency::new("opt_dep", "1.0").optional(true)) + .publish(); + Package::new("opt_dep", "1.0.0").publish(); + + Package::new("bar", "1.0.0") + .add_dep( + Dependency::new("common", "1.0") + .target("cfg(whatever)") + .enable_features(&["f1"]), + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + common = "1.0" + bar = "1.0" + + [build-dependencies] + common = { version = "1.0", features = ["opt_dep"] } + + [dev-dependencies] + common = { version="1.0", features=["dev-feat"] } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2018 edition to 2021 +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] common v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] opt_dep v1.0.0 (registry `dummy-registry`) +[NOTE] Switching to Edition 2021 will enable the use of the version 2 feature resolver in Cargo. +This may cause some dependencies to be built with fewer features enabled than previously. +More information about the resolver changes may be found at https://doc.rust-lang.org/nightly/edition-guide/rust-2021/default-cargo-resolver.html +When building the following dependencies, the given features will no longer be used: + + common v1.0.0 removed features: dev-feat, f1, opt_dep + common v1.0.0 (as host dependency) removed features: dev-feat, f1 + +The following differences only apply when building with dev-dependencies: + + common v1.0.0 removed features: f1, opt_dep + +[CHECKING] opt_dep v1.0.0 +[CHECKING] common v1.0.0 +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2018 edition to 2021 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn rustfix_handles_multi_spans() { + // Checks that rustfix handles a single diagnostic with multiple + // suggestion spans (non_fmt_panic in this case). + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file( + "src/lib.rs", + r#" + pub fn foo() { + panic!(format!("hey")); + } + "#, + ) + .build(); + + p.cargo("fix --allow-no-vcs").run(); + assert!(p.read_file("src/lib.rs").contains(r#"panic!("hey");"#)); +} + +#[cargo_test] +fn fix_edition_2021() { + // Can migrate 2021, even when lints are allowed. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + "#, + ) + .file( + "src/lib.rs", + r#" + #![allow(ellipsis_inclusive_range_patterns)] + + pub fn f() -> bool { + let x = 123; + match x { + 0...100 => true, + _ => false, + } + } + "#, + ) + .build(); + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2018 edition to 2021 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2018 edition to 2021 +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.read_file("src/lib.rs").contains(r#"0..=100 => true,"#)); +} + +#[cargo_test] +fn fix_shared_cross_workspace() { + // Fixing a file that is shared between multiple packages in the same workspace. + // Make sure two processes don't try to fix the same file at the same time. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "pub mod shared;") + // This will fix both unused and bare trait. + .file("foo/src/shared.rs", "pub fn fixme(x: Box<&Fn() -> ()>) {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file( + "bar/src/lib.rs", + r#" + #[path="../../foo/src/shared.rs"] + pub mod shared; + "#, + ) + .build(); + + // The output here can be either of these two, depending on who runs first: + // [FIXED] bar/src/../../foo/src/shared.rs (2 fixes) + // [FIXED] foo/src/shared.rs (2 fixes) + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stderr_data( + str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo/foo) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FIXED] [..]foo/src/shared.rs (2 fixes) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + assert_e2e().eq( + &p.read_file("foo/src/shared.rs"), + str!["pub fn fixme(_x: Box<&dyn Fn() -> ()>) {}"], + ); +} + +#[cargo_test] +fn abnormal_exit() { + // rustc fails unexpectedly after applying fixes, should show some error information. + // + // This works with a proc-macro that runs twice: + // - First run (collect diagnostics pass): writes a file, exits normally. + // - Second run (verify diagnostics work): it detects the presence of the + // file, removes the file, and aborts the process. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + pm = {path="pm"} + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn f() { + let mut x = 1; + pm::crashme!(); + } + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2018" + + [lib] + proc-macro = true + "#, + ) + .file( + "pm/src/lib.rs", + r#" + use proc_macro::TokenStream; + #[proc_macro] + pub fn crashme(_input: TokenStream) -> TokenStream { + // Use a file to succeed on the first pass, and fail on the second. + let p = std::env::var_os("ONCE_PATH").unwrap(); + let check_path = std::path::Path::new(&p); + if check_path.exists() { + eprintln!("I'm not a diagnostic."); + std::fs::remove_file(check_path).unwrap(); + std::process::abort(); + } else { + std::fs::write(check_path, "").unwrap(); + "".parse().unwrap() + } + } + "#, + ) + .build(); + + p.cargo("fix --lib --allow-no-vcs") + .env( + "ONCE_PATH", + paths::root().join("proc-macro-run-once").to_str().unwrap(), + ) + // "signal: 6, SIGABRT: process abort signal" on some platforms + .with_stderr_data(str![[r#" +... +[WARNING] failed to automatically apply fixes suggested by rustc to crate `foo` +... +I'm not a diagnostic. +rustc exited abnormally: [..] +Original diagnostics will follow. +... +"#]]) + .run(); +} + +#[cargo_test] +fn fix_with_run_cargo_in_proc_macros() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + use proc_macro::*; + + #[proc_macro] + pub fn foo(_input: TokenStream) -> TokenStream { + let output = std::process::Command::new(env!("CARGO")) + .args(&["metadata", "--format-version=1"]) + .output() + .unwrap(); + eprintln!("{}", std::str::from_utf8(&output.stderr).unwrap()); + println!("{}", std::str::from_utf8(&output.stdout).unwrap()); + "".parse().unwrap() + } + "#, + ) + .file( + "src/bin/main.rs", + r#" + use foo::foo; + + fn main() { + foo!("bar") + } + "#, + ) + .build(); + p.cargo("fix --allow-no-vcs") + .with_stderr_does_not_contain("error: could not find .rs file in rustc args") + .run(); +} + +#[cargo_test] +fn non_edition_lint_migration() { + // Migrating to a new edition where a non-edition lint causes problems. + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file( + "src/lib.rs", + r#" + // This is only used in a test. + // To be correct, this should be gated on #[cfg(test)], but + // sometimes people don't do that. If the unused_imports + // lint removes this, then the unittest will fail to compile. + use std::str::from_utf8; + + pub mod foo { + pub const FOO: &[u8] = &[102, 111, 111]; + } + + #[test] + fn example() { + assert_eq!( + from_utf8(::foo::FOO), Ok("foo") + ); + } + "#, + ) + .build(); + // Check that it complains about an unused import. + p.cargo("check --lib") + .with_stderr_data(str![[r#" +... +[..]use std::str::from_utf8; +... + = [NOTE] `#[warn(unused_imports)]` on by default +... +"#]]) + .run(); + p.cargo("fix --edition --allow-no-vcs").run(); + let contents = p.read_file("src/lib.rs"); + // Check it does not remove the "unused" import. + assert!(contents.contains("use std::str::from_utf8;")); + // Check that it made the edition migration. + assert!(contents.contains("from_utf8(crate::foo::FOO)")); +} + +#[cargo_test] +fn fix_in_dependency() { + // Tests what happens if rustc emits a suggestion to modify a file from a + // dependency in cargo's home directory. This should never happen, and + // indicates a bug in rustc. However, there are several known bugs in + // rustc where it does this (often involving macros), so `cargo fix` has a + // guard that says if the suggestion points to some location in CARGO_HOME + // to not apply it. + // + // See https://github.com/rust-lang/cargo/issues/9857 for some other + // examples. + // + // This test uses a simulated rustc which replays a suggestion via a JSON + // message that points into CARGO_HOME. This does not use the real rustc + // because as the bugs are fixed in the real rustc, that would cause this + // test to stop working. + Package::new("bar", "1.0.0") + .file( + "src/lib.rs", + r#" + #[macro_export] + macro_rules! m { + ($i:tt) => { + let $i = 1; + }; + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() { + bar::m!(abc); + } + "#, + ) + .build(); + p.cargo("fetch").run(); + + // The path in CARGO_HOME. + let bar_path = std::fs::read_dir(paths::home().join(".cargo/registry/src")) + .unwrap() + .next() + .unwrap() + .unwrap() + .path(); + // Since this is a substitution into a Rust string (representing a JSON + // string), deal with backslashes like on Windows. + let bar_path_str = bar_path.to_str().unwrap().replace("\\", "/"); + + // This is a fake rustc that will emit a JSON message when the `foo` crate + // builds that tells cargo to modify a file it shouldn't. + let rustc = project() + .at("rustc-replay") + .file("Cargo.toml", &basic_manifest("rustc-replay", "1.0.0")) + .file("src/main.rs", + &r##" + fn main() { + let pkg_name = match std::env::var("CARGO_PKG_NAME") { + Ok(pkg_name) => pkg_name, + Err(_) => { + let r = std::process::Command::new("rustc") + .args(std::env::args_os().skip(1)) + .status(); + std::process::exit(r.unwrap().code().unwrap_or(2)); + } + }; + if pkg_name == "foo" { + eprintln!("{}", r#"{ + "$message_type": "diagnostic", + "message": "unused variable: `abc`", + "code": + { + "code": "unused_variables", + "explanation": null + }, + "level": "warning", + "spans": + [ + { + "file_name": "__BAR_PATH__/bar-1.0.0/src/lib.rs", + "byte_start": 127, + "byte_end": 129, + "line_start": 5, + "line_end": 5, + "column_start": 29, + "column_end": 31, + "is_primary": true, + "text": + [ + { + "text": " let $i = 1;", + "highlight_start": 29, + "highlight_end": 31 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": + [ + { + "message": "`#[warn(unused_variables)]` on by default", + "code": null, + "level": "note", + "spans": + [], + "children": + [], + "rendered": null + }, + { + "message": "if this is intentional, prefix it with an underscore", + "code": null, + "level": "help", + "spans": + [ + { + "file_name": "__BAR_PATH__/bar-1.0.0/src/lib.rs", + "byte_start": 127, + "byte_end": 129, + "line_start": 5, + "line_end": 5, + "column_start": 29, + "column_end": 31, + "is_primary": true, + "text": + [ + { + "text": " let $i = 1;", + "highlight_start": 29, + "highlight_end": 31 + } + ], + "label": null, + "suggested_replacement": "_abc", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": + [], + "rendered": null + } + ], + "rendered": "warning: unused variable: `abc`\n --> __BAR_PATH__/bar-1.0.0/src/lib.rs:5:29\n |\n5 | let $i = 1;\n | ^^ help: if this is intentional, prefix it with an underscore: `_abc`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n" + }"#.replace("\n", "")); + } + } + "##.replace("__BAR_PATH__", &bar_path_str)) + .build(); + rustc.cargo("build").run(); + let rustc_bin = rustc.bin("rustc-replay"); + + // The output here should not say `Fixed`. + // + // It is OK to compare the full diagnostic output here because the text is + // hard-coded in rustc-replay. Normally tests should not be checking the + // compiler output. + p.cargo("fix --lib --allow-no-vcs") + .env("RUSTC", &rustc_bin) + .with_stderr_data(str![[r#" +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[WARNING] unused variable: `abc` + --> [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/src/lib.rs:5:29 + | +5 | let $i = 1; + | ^^ [HELP] if this is intentional, prefix it with an underscore: `_abc` + | + = [NOTE] `#[warn(unused_variables)]` on by default + +[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fix_in_rust_src() { + // Tests what happens if rustc emits a suggestion to modify the standard + // library in rust source. This should never happen, and indicates a bug in + // rustc. However, there are several known bugs in rustc where it does this + // (often involving macros), so `cargo fix` has a guard that says if the + // suggestion points to rust source under sysroot to not apply it. + // + // See https://github.com/rust-lang/cargo/issues/9857 for some other + // examples. + // + // This test uses a simulated rustc which replays a suggestion via a JSON + // message that points into rust-src. This does not use the real rustc + // because as the bugs are fixed in the real rustc, that would cause this + // test to stop working. + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2021" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn bug_report(w: &mut W) -> std::fmt::Result { + if true { + writeln!(w, "`;?` here ->")?; + } else { + writeln!(w, "but not here") + } + Ok(()) + } + "#, + ) + .build(); + p.cargo("fetch").run(); + + // Since this is a substitution into a Rust string (representing a JSON + // string), deal with backslashes like on Windows. + let sysroot = paths::sysroot().replace("\\", "/"); + + // This is a fake rustc that will emit a JSON message when the `foo` crate + // builds that tells cargo to modify a file it shouldn't. + let rustc = project() + .at("rustc-replay") + .file("Cargo.toml", &basic_manifest("rustc-replay", "1.0.0")) + .file("src/main.rs", + &r##" + fn main() { + let pkg_name = match std::env::var("CARGO_PKG_NAME") { + Ok(pkg_name) => pkg_name, + Err(_) => { + let r = std::process::Command::new("rustc") + .args(std::env::args_os().skip(1)) + .status(); + std::process::exit(r.unwrap().code().unwrap_or(2)); + } + }; + if pkg_name == "foo" { + eprintln!("{}", r#"{ + "$message_type": "diagnostic", + "message": "mismatched types", + "code": + { + "code": "E0308", + "explanation": "Expected type did not match the received type.\n\nErroneous code examples:\n\n```compile_fail,E0308\nfn plus_one(x: i32) -> i32 {\n x + 1\n}\n\nplus_one(\"Not a number\");\n// ^^^^^^^^^^^^^^ expected `i32`, found `&str`\n\nif \"Not a bool\" {\n// ^^^^^^^^^^^^ expected `bool`, found `&str`\n}\n\nlet x: f32 = \"Not a float\";\n// --- ^^^^^^^^^^^^^ expected `f32`, found `&str`\n// |\n// expected due to this\n```\n\nThis error occurs when an expression was used in a place where the compiler\nexpected an expression of a different type. It can occur in several cases, the\nmost common being when calling a function and passing an argument which has a\ndifferent type than the matching type in the function declaration.\n" + }, + "level": "error", + "spans": + [ + { + "file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs", + "byte_start": 23568, + "byte_end": 23617, + "line_start": 670, + "line_end": 670, + "column_start": 9, + "column_end": 58, + "is_primary": true, + "text": + [ + { + "text": " $dst.write_fmt($crate::format_args_nl!($($arg)*))", + "highlight_start": 9, + "highlight_end": 58 + } + ], + "label": "expected `()`, found `Result<(), Error>`", + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": + { + "span": + { + "file_name": "lib.rs", + "byte_start": 144, + "byte_end": 171, + "line_start": 5, + "line_end": 5, + "column_start": 9, + "column_end": 36, + "is_primary": false, + "text": + [ + { + "text": " writeln!(w, \"but not here\")", + "highlight_start": 9, + "highlight_end": 36 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + }, + "macro_decl_name": "writeln!", + "def_site_span": + { + "file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs", + "byte_start": 23434, + "byte_end": 23454, + "line_start": 665, + "line_end": 665, + "column_start": 1, + "column_end": 21, + "is_primary": false, + "text": + [ + { + "text": "macro_rules! writeln {", + "highlight_start": 1, + "highlight_end": 21 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + } + }, + { + "file_name": "lib.rs", + "byte_start": 75, + "byte_end": 177, + "line_start": 2, + "line_end": 6, + "column_start": 5, + "column_end": 6, + "is_primary": false, + "text": + [ + { + "text": " if true {", + "highlight_start": 5, + "highlight_end": 14 + }, + { + "text": " writeln!(w, \"`;?` here ->\")?;", + "highlight_start": 1, + "highlight_end": 38 + }, + { + "text": " } else {", + "highlight_start": 1, + "highlight_end": 13 + }, + { + "text": " writeln!(w, \"but not here\")", + "highlight_start": 1, + "highlight_end": 36 + }, + { + "text": " }", + "highlight_start": 1, + "highlight_end": 6 + } + ], + "label": "expected this to be `()`", + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": + [ + { + "message": "use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller", + "code": null, + "level": "help", + "spans": + [ + { + "file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs", + "byte_start": 23617, + "byte_end": 23617, + "line_start": 670, + "line_end": 670, + "column_start": 58, + "column_end": 58, + "is_primary": true, + "text": + [ + { + "text": " $dst.write_fmt($crate::format_args_nl!($($arg)*))", + "highlight_start": 58, + "highlight_end": 58 + } + ], + "label": null, + "suggested_replacement": "?", + "suggestion_applicability": "HasPlaceholders", + "expansion": + { + "span": + { + "file_name": "lib.rs", + "byte_start": 144, + "byte_end": 171, + "line_start": 5, + "line_end": 5, + "column_start": 9, + "column_end": 36, + "is_primary": false, + "text": + [ + { + "text": " writeln!(w, \"but not here\")", + "highlight_start": 9, + "highlight_end": 36 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + }, + "macro_decl_name": "writeln!", + "def_site_span": + { + "file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs", + "byte_start": 23434, + "byte_end": 23454, + "line_start": 665, + "line_end": 665, + "column_start": 1, + "column_end": 21, + "is_primary": false, + "text": + [ + { + "text": "macro_rules! writeln {", + "highlight_start": 1, + "highlight_end": 21 + } + ], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + } + } + ], + "children": + [], + "rendered": null + } + ], + "rendered": "error[E0308]: mismatched types\n --> lib.rs:5:9\n |\n2 | / if true {\n3 | | writeln!(w, \"`;?` here ->\")?;\n4 | | } else {\n5 | | writeln!(w, \"but not here\")\n | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`\n6 | | }\n | |_____- expected this to be `()`\n |\n = note: expected unit type `()`\n found enum `Result<(), std::fmt::Error>`\n = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider using a semicolon here\n |\n6 | };\n | +\nhelp: you might have meant to return this value\n |\n5 | return writeln!(w, \"but not here\");\n | ++++++ +\nhelp: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller\n --> __SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58\n |\n67| $dst.write_fmt($crate::format_args_nl!($($arg)*))?\n | +\n\n" +}"#.replace("\n", "")); + + std::process::exit(2); + } + } + "##.replace("__SYSROOT__", &sysroot)) + .build(); + rustc.cargo("build").run(); + let rustc_bin = rustc.bin("rustc-replay"); + + // The output here should not say `Fixed`. + // + // It is OK to compare the full diagnostic output here because the text is + // hard-coded in rustc-replay. Normally tests should not be checking the + // compiler output. + p.cargo("fix --lib --allow-no-vcs --broken-code") + .env("__CARGO_FIX_YOLO", "1") + .env("RUSTC", &rustc_bin) + .with_status(101) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.0 ([ROOT]/foo) +error[E0308]: mismatched types + --> lib.rs:5:9 + | +2 | / if true { +3 | | writeln!(w, "`;?` here ->")?; +4 | | } else { +5 | | writeln!(w, "but not here") + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>` +6 | | } + | |_____- expected this to be `()` + | + = [NOTE] expected unit type `()` + found enum `Result<(), std::fmt::Error>` + = [NOTE] this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info) +[HELP] consider using a semicolon here + | +6 | }; + | + +[HELP] you might have meant to return this value + | +5 | return writeln!(w, "but not here"); + | ++++++ + +[HELP] use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller + --> [..]/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58 + | +67| $dst.write_fmt($crate::format_args_nl!($($arg)*))? + | + + +[ERROR] could not compile `foo` (lib) due to 1 previous error + +"#]]) + .run(); +} + +// See +#[cargo_test] +fn fix_only_once_for_duplicates() { + let p = project() + .file( + "src/main.rs", + r#" +macro_rules! foo { + () => { + &1; + }; +} + +fn main() { + foo!(); + foo!(); +} +"#, + ) + .build(); + + p.cargo("fix --allow-no-vcs") + .env("__CARGO_FIX_YOLO", "1") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FIXED] src/main.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert_e2e().eq( + p.read_file("src/main.rs"), + str![[r#" + +macro_rules! foo { + () => { + let _ = &1; + }; +} + +fn main() { + foo!(); + foo!(); +} + +"#]], + ); +} + +#[cargo_test] +fn migrate_project_to_package() { + let p = project() + .file( + "Cargo.toml", + r#" +# Before project +[ project ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table +"#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2021 edition to 2024 +[FIXED] Cargo.toml (1 fix) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_e2e().eq( + p.read_file("Cargo.toml"), + str![[r#" + +# Before project +[ package ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table + +"#]], + ); +} + +#[cargo_test] +fn migrate_removes_project() { + let p = project() + .file( + "Cargo.toml", + r#" +# Before package +[ package ] # After package header +# After package header line +name = "foo" +edition = "2021" +# After package table + +# Before project +[ project ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table +"#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2021 edition to 2024 +[FIXED] Cargo.toml (1 fix) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_e2e().eq( + p.read_file("Cargo.toml"), + str![[r#" + +# Before package +[ package ] # After package header +# After package header line +name = "foo" +edition = "2021" +# After project table + +"#]], + ); +} + +#[cargo_test] +fn migrate_removes_project_for_script() { + let p = project() + .file( + "foo.rs", + r#" +--- +# Before package +[ package ] # After package header +# After package header line +name = "foo" +edition = "2021" +# After package table + +# Before project +[ project ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table +--- + +fn main() { +} +"#, + ) + .build(); + + p.cargo("-Zscript fix --edition --allow-no-vcs --manifest-path foo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stderr_data(str![[r#" +[MIGRATING] foo.rs from 2021 edition to 2024 +[FIXED] foo.rs (1 fix) +[CHECKING] foo v0.0.0 ([ROOT]/foo/foo.rs) +[MIGRATING] [ROOT]/home/.cargo/target/[HASH]/foo.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_e2e().eq( + p.read_file("foo.rs"), + str![[r#" + +--- +# Before package +[ package ] # After package header +# After package header line +name = "foo" +edition = "2021" +# After project table +--- + +fn main() { +} + +"#]], + ); +} + +#[cargo_test] +fn migrate_rename_underscore_fields() { + let p = project() + .file( + "Cargo.toml", + r#" +[workspace.dependencies] +# Before default_features +a = {path = "a", default_features = false} # After default_features value +# After default_features line + +[package] +name = "foo" +edition = "2021" + +[lib] +name = "foo" +# Before crate_type +crate_type = ["staticlib", "dylib"] # After crate_type value +# After crate_type line + +[[example]] +name = "ex" +path = "examples/ex.rs" +# Before crate_type +crate_type = ["proc-macro"] # After crate_type value +# After crate_type line + +# Before dev_dependencies +[ dev_dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default_features = false} +# After dev_dependencies table + +# Before build_dependencies +[ build_dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default_features = false} +# After build_dependencies table + +# Before dev_dependencies +[ target.'cfg(any())'.dev_dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default_features = false} +# After dev_dependencies table + +# Before build_dependencies +[ target.'cfg(any())'.build_dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default_features = false} +# After build_dependencies table +"#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + fn main() { println!("ex"); } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2021 edition to 2024 +[FIXED] Cargo.toml (11 fixes) +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[MIGRATING] src/lib.rs from 2021 edition to 2024 +[MIGRATING] examples/ex.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_e2e().eq( + p.read_file("Cargo.toml"), + str![[r#" + +[workspace.dependencies] +# Before default_features +a = {path = "a", default-features = false} # After default_features value +# After default_features line + +[package] +name = "foo" +edition = "2021" + +[lib] +name = "foo" +# Before crate_type +crate-type = ["staticlib", "dylib"] # After crate_type value +# After crate_type line + +[[example]] +name = "ex" +path = "examples/ex.rs" +# Before crate_type +crate-type = ["proc-macro"] # After crate_type value +# After crate_type line + +# Before dev_dependencies +[ dev-dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default-features = false} +# After dev_dependencies table + +# Before build_dependencies +[ build-dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default-features = false} +# After build_dependencies table + +# Before dev_dependencies +[ target.'cfg(any())'.dev-dependencies ] # After dev_dependencies header +# After dev_dependencies line +a = {path = "a", default-features = false} +# After dev_dependencies table + +# Before build_dependencies +[ target.'cfg(any())'.build-dependencies ] # After build_dependencies header +# After build_dependencies line +a = {path = "a", default-features = false} +# After build_dependencies table + +"#]], + ); +} + +#[cargo_test] +fn migrate_rename_underscore_fields_in_virtual_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" +[workspace] +members = ["foo"] +resolver = "2" + +[workspace.dependencies] +# Before default_features +a = {path = "a", default_features = false} # After default_features value +# After default_features line +"#, + ) + .file( + "foo/Cargo.toml", + r#" +[package] +name = "foo" +edition = "2021" +"#, + ) + .file("foo/src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .with_stderr_data(str![[r#" +[MIGRATING] Cargo.toml from 2021 edition to 2024 +[FIXED] Cargo.toml (1 fix) +[MIGRATING] foo/Cargo.toml from 2021 edition to 2024 +[CHECKING] foo v0.0.0 ([ROOT]/foo/foo) +[MIGRATING] foo/src/lib.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_e2e().eq( + p.read_file("Cargo.toml"), + str![[r#" + +[workspace] +members = ["foo"] +resolver = "2" + +[workspace.dependencies] +# Before default_features +a = {path = "a", default-features = false} # After default_features value +# After default_features line + +"#]], + ); + assert_e2e().eq( + p.read_file("foo/Cargo.toml"), + str![[r#" + +[package] +name = "foo" +edition = "2021" + +"#]], + ); +} + +#[cargo_test] +fn remove_ignored_default_features() { + Package::new("dep_simple", "0.1.0").publish(); + Package::new("dep_df_true", "0.1.0").publish(); + Package::new("dep_df_false", "0.1.0").publish(); + + let pkg_default = r#" +[package] +name = "pkg_default" +version = "0.1.0" +edition = "2021" + +[dependencies] +dep_simple = { workspace = true } +dep_df_true = { workspace = true } +dep_df_false = { workspace = true } + +[build-dependencies] +dep_simple = { workspace = true } +dep_df_true = { workspace = true } +dep_df_false = { workspace = true } + +[target.'cfg(target_os = "linux")'.dependencies] +dep_simple = { workspace = true } +dep_df_true = { workspace = true } +dep_df_false = { workspace = true } +"#; + let pkg_df_true = r#" +[package] +name = "pkg_df_true" +version = "0.1.0" +edition = "2021" + +[dependencies] +dep_simple = { workspace = true, default-features = true } +dep_df_true = { workspace = true, default-features = true } +dep_df_false = { workspace = true, default-features = true } + +[build-dependencies] +dep_simple = { workspace = true, default-features = true } +dep_df_true = { workspace = true, default-features = true } +dep_df_false = { workspace = true, default-features = true } + +[target.'cfg(target_os = "linux")'.dependencies] +dep_simple = { workspace = true, default-features = true } +dep_df_true = { workspace = true, default-features = true } +dep_df_false = { workspace = true, default-features = true } +"#; + let pkg_df_false = r#" +[package] +name = "pkg_df_false" +version = "0.1.0" +edition = "2021" + +[dependencies] +dep_simple = { workspace = true, default-features = false } +dep_df_true = { workspace = true, default-features = false } +dep_df_false = { workspace = true, default-features = false } + +[build-dependencies] +dep_simple = { workspace = true, default-features = false } +dep_df_true = { workspace = true, default-features = false } +dep_df_false = { workspace = true, default-features = false } + +[target.'cfg(target_os = "linux")'.dependencies] +dep_simple = { workspace = true, default-features = false } +dep_df_true = { workspace = true, default-features = false } +dep_df_false = { workspace = true, default-features = false } +"#; + let p = project() + .file( + "Cargo.toml", + r#" +[workspace] +members = ["pkg_default", "pkg_df_true", "pkg_df_false"] +resolver = "2" + +[workspace.dependencies] +dep_simple = "0.1.0" +dep_df_true = { version = "0.1.0", default-features = true } +dep_df_false = { version = "0.1.0", default-features = false } +"#, + ) + .file("pkg_default/Cargo.toml", pkg_default) + .file("pkg_default/src/lib.rs", "") + .file("pkg_df_true/Cargo.toml", pkg_df_true) + .file("pkg_df_true/src/lib.rs", "") + .file("pkg_df_false/Cargo.toml", pkg_df_false) + .file("pkg_df_false/src/lib.rs", "") + .build(); + + p.cargo("fix --all --edition --allow-no-vcs") + .with_stderr_data( + str![[r#" +[MIGRATING] pkg_default/Cargo.toml from 2021 edition to 2024 +[MIGRATING] pkg_df_true/Cargo.toml from 2021 edition to 2024 +[MIGRATING] pkg_df_false/Cargo.toml from 2021 edition to 2024 +[FIXED] pkg_df_false/Cargo.toml (6 fixes) +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] dep_simple v0.1.0 (registry `dummy-registry`) +[DOWNLOADED] dep_df_true v0.1.0 (registry `dummy-registry`) +[DOWNLOADED] dep_df_false v0.1.0 (registry `dummy-registry`) +[CHECKING] dep_df_true v0.1.0 +[CHECKING] dep_df_false v0.1.0 +[CHECKING] dep_simple v0.1.0 +[CHECKING] pkg_df_true v0.1.0 ([ROOT]/foo/pkg_df_true) +[CHECKING] pkg_df_false v0.1.0 ([ROOT]/foo/pkg_df_false) +[CHECKING] pkg_default v0.1.0 ([ROOT]/foo/pkg_default) +[MIGRATING] pkg_df_false/src/lib.rs from 2021 edition to 2024 +[MIGRATING] pkg_df_true/src/lib.rs from 2021 edition to 2024 +[MIGRATING] pkg_default/src/lib.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + assert_e2e().eq(p.read_file("pkg_default/Cargo.toml"), pkg_default); + assert_e2e().eq(p.read_file("pkg_df_true/Cargo.toml"), pkg_df_true); + assert_e2e().eq( + p.read_file("pkg_df_false/Cargo.toml"), + str![[r#" + +[package] +name = "pkg_df_false" +version = "0.1.0" +edition = "2021" + +[dependencies] +dep_simple = { workspace = true} +dep_df_true = { workspace = true} +dep_df_false = { workspace = true, default-features = false } + +[build-dependencies] +dep_simple = { workspace = true} +dep_df_true = { workspace = true} +dep_df_false = { workspace = true, default-features = false } + +[target.'cfg(target_os = "linux")'.dependencies] +dep_simple = { workspace = true} +dep_df_true = { workspace = true} +dep_df_false = { workspace = true, default-features = false } + +"#]], + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix_n_times.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix_n_times.rs new file mode 100644 index 000000000..179602ff0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/fix_n_times.rs @@ -0,0 +1,522 @@ +//! Tests for the `cargo fix` command, specifically targeting the logic around +//! running rustc multiple times to apply and verify fixes. +//! +//! These tests use a replacement of rustc ("rustc-fix-shim") which emits JSON +//! messages based on what the test is exercising. It uses an environment +//! variable `RUSTC_FIX_SHIM_SEQUENCE` which determines how it should behave +//! based on how many times `rustc` has run. It keeps track of how many times +//! rustc has run in a local file. +//! +//! For example, a sequence of `[Step::OneFix, Step::Error]` will emit one +//! suggested fix the first time `rustc` is run, and then the next time it is +//! run it will generate an error. +//! +//! The [`expect_fix_runs_rustc_n_times`] function handles setting everything +//! up, and verifying the results. + +use std::path::PathBuf; +use std::sync::{Mutex, OnceLock}; + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, paths, project, str, tools, Execs}; + +/// The action that the `rustc` shim should take in the current sequence of +/// events. +#[derive(Clone, Copy, PartialEq)] +#[repr(u8)] +enum Step { + /// Exits with success with no messages. + SuccessNoOutput = b'0', + /// Emits one suggested fix. + /// + /// The suggested fix involves updating the number of the first line + /// comment which starts as `// fix-count 0`. + OneFix = b'1', + /// Emits two suggested fixes which overlap, which rustfix can only apply + /// one of them, and fails for the other. + /// + /// The suggested fix is the same as `Step::OneFix`, it just shows up + /// twice. + TwoFixOverlapping = b'2', + /// Generates a warning without a suggestion. + Warning = b'w', + /// Generates an error message with no suggestion. + Error = b'e', + /// Emits one suggested fix and an error. + OneFixError = b'f', +} + +/// Verifies `cargo fix` behavior based on the given sequence of behaviors for +/// `rustc`. +/// +/// - `sequence` is the sequence of behaviors for each call to `rustc`. +/// If rustc is called more often than the number of steps, then it will panic. +/// - `extra_execs` a callback that allows extra customization of the [`Execs`]. +/// - `expected_stderr` is the expected output from cargo. +/// - `expected_lib_rs` is the expected contents of `src/lib.rs` after the +/// fixes have been applied. The file starts out with the content `// +/// fix-count 0`, and the number increases based on which suggestions are +/// applied. +fn expect_fix_runs_rustc_n_times( + sequence: &[Step], + extra_execs: impl FnOnce(&mut Execs), + expected_stderr: impl IntoData, + expected_lib_rs: &str, +) { + let rustc = rustc_for_cargo_fix(); + let p = project().file("src/lib.rs", "// fix-count 0").build(); + + let sequence_vec: Vec<_> = sequence.iter().map(|x| *x as u8).collect(); + let sequence_str = std::str::from_utf8(&sequence_vec).unwrap(); + + let mut execs = p.cargo("fix --allow-no-vcs --lib"); + execs + .env("RUSTC", &rustc) + .env("RUSTC_FIX_SHIM_SEQUENCE", sequence_str) + .with_stderr_data(expected_stderr); + extra_execs(&mut execs); + execs.run(); + let lib_rs = p.read_file("src/lib.rs"); + assert_eq!(expected_lib_rs, lib_rs); + let count: usize = p.read_file("rustc-fix-shim-count").parse().unwrap(); + assert_eq!(sequence.len(), count); +} + +/// Returns the path to the rustc replacement executable. +fn rustc_for_cargo_fix() -> PathBuf { + static FIX_SHIM: OnceLock>> = OnceLock::new(); + + let mut lock = FIX_SHIM.get_or_init(|| Default::default()).lock().unwrap(); + if let Some(path) = &*lock { + return path.clone(); + } + + let p = project() + .at(paths::global_root().join("rustc-fix-shim")) + .file("Cargo.toml", &basic_manifest("rustc-fix-shim", "1.0.0")) + .file( + "src/main.rs", + r##" +fn main() { + if std::env::var_os("CARGO_PKG_NAME").is_none() { + // Handle things like rustc -Vv + let r = std::process::Command::new("rustc") + .args(std::env::args_os().skip(1)) + .status(); + std::process::exit(r.unwrap().code().unwrap_or(2)); + } + + // Keep track of which step in the sequence that needs to run. + let successful_count = std::fs::read_to_string("rustc-fix-shim-count") + .map(|c| c.parse().unwrap()) + .unwrap_or(0); + std::fs::write("rustc-fix-shim-count", format!("{}", successful_count + 1)).unwrap(); + // The sequence tells us which behavior we should have. + let seq = std::env::var("RUSTC_FIX_SHIM_SEQUENCE").unwrap(); + if successful_count >= seq.len() { + panic!("rustc called too many times count={}, \ + make sure to update the Step sequence", successful_count); + } + match seq.as_bytes()[successful_count] { + b'0' => return, + b'1' => { + output_suggestion(successful_count + 1); + } + b'2' => { + output_suggestion(successful_count + 1); + output_suggestion(successful_count + 2); + } + b'w' => { + output_message("warning", successful_count + 1); + } + b'e' => { + output_message("error", successful_count + 1); + std::process::exit(1); + } + b'f' => { + output_suggestion(successful_count + 1); + output_message("error", successful_count + 2); + std::process::exit(1); + } + _ => panic!("unexpected sequence"), + } +} + +fn output_suggestion(count: usize) { + let json = format!( + r#"{{ + "$message_type": "diagnostic", + "message": "rustc fix shim comment {count}", + "code": null, + "level": "warning", + "spans": + [ + {{ + "file_name": "src/lib.rs", + "byte_start": 13, + "byte_end": 14, + "line_start": 1, + "line_end": 1, + "column_start": 14, + "column_end": 15, + "is_primary": true, + "text": + [ + {{ + "text": "// fix-count 0", + "highlight_start": 14, + "highlight_end": 15 + }} + ], + "label": "increase this number", + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + }} + ], + "children": + [ + {{ + "message": "update the number here", + "code": null, + "level": "help", + "spans": + [ + {{ + "file_name": "src/lib.rs", + "byte_start": 13, + "byte_end": 14, + "line_start": 1, + "line_end": 1, + "column_start": 14, + "column_end": 15, + "is_primary": true, + "text": + [ + {{ + "text": "// fix-count 0", + "highlight_start": 14, + "highlight_end": 15 + }} + ], + "label": null, + "suggested_replacement": "{count}", + "suggestion_applicability": "MachineApplicable", + "expansion": null + }} + ], + "children": [], + "rendered": null + }} + ], + "rendered": "rustc fix shim comment {count}" + }}"#, + ) + .replace("\n", ""); + eprintln!("{json}"); +} + +fn output_message(level: &str, count: usize) { + let json = format!( + r#"{{ + "$message_type": "diagnostic", + "message": "rustc fix shim {level} count={count}", + "code": null, + "level": "{level}", + "spans": + [ + {{ + "file_name": "src/lib.rs", + "byte_start": 0, + "byte_end": 0, + "line_start": 1, + "line_end": 1, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": + [ + {{ + "text": "// fix-count 0", + "highlight_start": 1, + "highlight_end": 4 + }} + ], + "label": "forced error", + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + }} + ], + "children": [], + "rendered": "rustc fix shim {level} count={count}" +}}"#, + ) + .replace("\n", ""); + eprintln!("{json}"); +} + "##, + ) + .build(); + p.cargo("build").run(); + let path = p.bin("rustc-fix-shim"); + *lock = Some(path.clone()); + path +} + +#[cargo_test] +fn fix_no_suggestions() { + // No suggested fixes. + expect_fix_runs_rustc_n_times( + &[Step::SuccessNoOutput], + |_execs| {}, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + "// fix-count 0", + ); +} + +#[cargo_test] +fn fix_one_suggestion() { + // One suggested fix, with a successful verification, no output. + expect_fix_runs_rustc_n_times( + &[Step::OneFix, Step::SuccessNoOutput], + |_execs| {}, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + "// fix-count 1", + ); +} + +#[cargo_test] +fn fix_one_overlapping() { + // Two suggested fixes, where one fails, then the next step returns no suggestions. + expect_fix_runs_rustc_n_times( + &[Step::TwoFixOverlapping, Step::SuccessNoOutput], + |_execs| {}, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FIXED] src/lib.rs (1 fix) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + "// fix-count 2", + ); +} + +#[cargo_test] +fn fix_overlapping_max() { + // Rustc repeatedly spits out suggestions that overlap, which should hit + // the limit of 4 attempts. It should show the output from the 5th attempt. + expect_fix_runs_rustc_n_times( + &[ + Step::TwoFixOverlapping, + Step::TwoFixOverlapping, + Step::TwoFixOverlapping, + Step::TwoFixOverlapping, + Step::TwoFixOverlapping, + ], + |_execs| {}, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] error applying suggestions to `src/lib.rs` + +The full error message was: + +> cannot replace slice of data that was already replaced + +This likely indicates a bug in either rustc or cargo itself, +and we would appreciate a bug report! You're likely to see +a number of compiler warnings after this message which cargo +attempted to fix but failed. If you could open an issue at +https://github.com/rust-lang/rust/issues +quoting the full output of this command we'd be very appreciative! +Note that you may be able to make some more progress in the near-term +fixing code with the `--broken-code` flag + +[FIXED] src/lib.rs (4 fixes) +rustc fix shim comment 5 +rustc fix shim comment 6 +[WARNING] `foo` (lib) generated 2 warnings (run `cargo fix --lib -p foo` to apply 2 suggestions) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + "// fix-count 5", + ); +} + +#[cargo_test] +fn fix_verification_failed() { + // One suggested fix, with an error in the verification step. + // This should cause `cargo fix` to back out the changes. + expect_fix_runs_rustc_n_times( + &[Step::OneFix, Step::Error], + |_execs| {}, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] failed to automatically apply fixes suggested by rustc to crate `foo` + +after fixes were automatically applied the compiler reported errors within these files: + + * src/lib.rs + +This likely indicates a bug in either rustc or cargo itself, +and we would appreciate a bug report! You're likely to see +a number of compiler warnings after this message which cargo +attempted to fix but failed. If you could open an issue at +https://github.com/rust-lang/rust/issues +quoting the full output of this command we'd be very appreciative! +Note that you may be able to make some more progress in the near-term +fixing code with the `--broken-code` flag + +The following errors were reported: +rustc fix shim error count=2 +Original diagnostics will follow. + +rustc fix shim comment 1 +[WARNING] `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply 1 suggestion) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + "// fix-count 0", + ); +} + +#[cargo_test] +fn fix_verification_failed_clippy() { + // This is the same as `fix_verification_failed_clippy`, except it checks + // the error message has the customization for the clippy URL and + // subcommand. + expect_fix_runs_rustc_n_times( + &[Step::OneFix, Step::Error], + |execs| { + execs.env("RUSTC_WORKSPACE_WRAPPER", tools::wrapped_clippy_driver()); + }, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] failed to automatically apply fixes suggested by rustc to crate `foo` + +after fixes were automatically applied the compiler reported errors within these files: + + * src/lib.rs + +This likely indicates a bug in either rustc or cargo itself, +and we would appreciate a bug report! You're likely to see +a number of compiler warnings after this message which cargo +attempted to fix but failed. If you could open an issue at +https://github.com/rust-lang/rust-clippy/issues +quoting the full output of this command we'd be very appreciative! +Note that you may be able to make some more progress in the near-term +fixing code with the `--broken-code` flag + +The following errors were reported: +rustc fix shim error count=2 +Original diagnostics will follow. + +rustc fix shim comment 1 +[WARNING] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + "// fix-count 0", + ); +} + +#[cargo_test] +fn warnings() { + // Only emits warnings. + expect_fix_runs_rustc_n_times( + &[Step::Warning], + |_execs| {}, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +rustc fix shim warning count=1 +[WARNING] `foo` (lib) generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + "// fix-count 0", + ); +} + +#[cargo_test] +fn starts_with_error() { + // The source code doesn't compile to start with. + expect_fix_runs_rustc_n_times( + &[Step::Error], + |execs| { + execs.with_status(101); + }, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +rustc fix shim error count=1 +[ERROR] could not compile `foo` (lib) due to 1 previous error + +"#]], + "// fix-count 0", + ); +} + +#[cargo_test] +fn broken_code_no_suggestions() { + // --broken-code with no suggestions + expect_fix_runs_rustc_n_times( + &[Step::Error], + |execs| { + execs.arg("--broken-code").with_status(101); + }, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +rustc fix shim error count=1 +[ERROR] could not compile `foo` (lib) due to 1 previous error + +"#]], + "// fix-count 0", + ); +} + +#[cargo_test] +fn broken_code_one_suggestion() { + // --broken-code where there is an error and a suggestion. + expect_fix_runs_rustc_n_times( + &[Step::OneFixError, Step::Error], + |execs| { + execs.arg("--broken-code").with_status(101); + }, + str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] failed to automatically apply fixes suggested by rustc to crate `foo` + +after fixes were automatically applied the compiler reported errors within these files: + + * src/lib.rs + +This likely indicates a bug in either rustc or cargo itself, +and we would appreciate a bug report! You're likely to see +a number of compiler warnings after this message which cargo +attempted to fix but failed. If you could open an issue at +https://github.com/rust-lang/rust/issues +quoting the full output of this command we'd be very appreciative! +Note that you may be able to make some more progress in the near-term +fixing code with the `--broken-code` flag + +The following errors were reported: +rustc fix shim error count=2 +Original diagnostics will follow. + +rustc fix shim comment 1 +rustc fix shim error count=2 +[WARNING] `foo` (lib) generated 1 warning +[ERROR] could not compile `foo` (lib) due to 1 previous error; 1 warning emitted + +"#]], + "// fix-count 1", + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness.rs new file mode 100644 index 000000000..7ad417e19 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness.rs @@ -0,0 +1,3184 @@ +//! Tests for fingerprinting (rebuild detection). + +use std::fs::{self, OpenOptions}; +use std::io; +use std::io::prelude::*; +use std::net::TcpListener; +use std::path::{Path, PathBuf}; +use std::process::Stdio; +use std::thread; +use std::time::SystemTime; + +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{ + basic_lib_manifest, basic_manifest, is_coarse_mtime, project, rustc_host, rustc_host_env, + sleep_ms, str, +}; +use filetime::FileTime; + +use super::death; + +#[cargo_test] +fn modifying_and_moving() { + let p = project() + .file("src/main.rs", "mod a; fn main() {}") + .file("src/a.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.root().move_into_the_past(); + p.root().join("target").move_into_the_past(); + + p.change_file("src/a.rs", "#[allow(unused)]fn main() {}"); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/a.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + fs::rename(&p.root().join("src/a.rs"), &p.root().join("src/b.rs")).unwrap(); + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +error[E0583]: file not found for module `a` +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test] +fn modify_only_some_files() { + let p = project() + .file("src/lib.rs", "mod a;") + .file("src/a.rs", "") + .file("src/main.rs", "mod b; fn main() {}") + .file("src/b.rs", "") + .file("tests/test.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("test").run(); + sleep_ms(1000); + + assert!(p.bin("foo").is_file()); + + let lib = p.root().join("src/lib.rs"); + p.change_file("src/lib.rs", "invalid rust code"); + p.change_file("src/b.rs", "#[allow(unused)]fn foo() {}"); + lib.move_into_the_past(); + + // Make sure the binary is rebuilt, not the lib + p.cargo("build -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/b.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn rebuild_sub_package_then_while_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [dependencies.a] + path = "a" + [dependencies.b] + path = "b" + "#, + ) + .file("src/lib.rs", "extern crate a; extern crate b;") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + authors = [] + version = "0.0.1" + edition = "2015" + [dependencies.b] + path = "../b" + "#, + ) + .file("a/src/lib.rs", "extern crate b;") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + if is_coarse_mtime() { + sleep_ms(1000); + } + p.change_file("b/src/lib.rs", "pub fn b() {}"); + + p.cargo("build -pb -v") + .with_stderr_data(str![[r#" +[DIRTY] b v0.0.1 ([ROOT]/foo/b): the file `b/src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[RUNNING] `rustc --crate-name b [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + "src/lib.rs", + "extern crate a; extern crate b; pub fn toplevel() {}", + ); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] b v0.0.1 ([ROOT]/foo/b) +[DIRTY] a v0.0.1 ([ROOT]/foo/a): the dependency b was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name a [..] +[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency b was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_lib_features_caches_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [features] + foo = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build --features foo") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + /* Targets should be cached from the first build */ + + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build --features foo") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_profiles_caches_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [profile.dev] + panic = "abort" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .run(); + + /* Targets should be cached from the first build */ + + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test foo") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_bin_paths_common_target_features_caches_targets() { + // Make sure dep_cache crate is built once per feature + let p = project() + .no_manifest() + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "./target" + "#, + ) + .file( + "dep_crate/Cargo.toml", + r#" + [package] + name = "dep_crate" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + ftest = [] + "#, + ) + .file( + "dep_crate/src/lib.rs", + r#" + #[cfg(feature = "ftest")] + pub fn yo() { + println!("ftest on") + } + #[cfg(not(feature = "ftest"))] + pub fn yo() { + println!("ftest off") + } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + dep_crate = {path = "../dep_crate", features = []} + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/src/main.rs", + r#" + extern crate dep_crate; + use dep_crate::yo; + fn main() { + yo(); + } + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + dep_crate = {path = "../dep_crate", features = ["ftest"]} + "#, + ) + .file("b/src/lib.rs", "") + .file( + "b/src/main.rs", + r#" + extern crate dep_crate; + use dep_crate::yo; + fn main() { + yo(); + } + "#, + ) + .build(); + + /* Build and rebuild a/. Ensure dep_crate only builds once */ + p.cargo("run") + .cwd("a") + .with_stdout_data(str![[r#" +ftest off + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate) +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]` + +"#]]) + .run(); + p.cargo("clean -p a").cwd("a").run(); + p.cargo("run") + .cwd("a") + .with_stdout_data(str![[r#" +ftest off + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]` + +"#]]) + .run(); + + /* Build and rebuild b/. Ensure dep_crate only builds once */ + p.cargo("run") + .cwd("b") + .with_stdout_data(str![[r#" +ftest on + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate) +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]` + +"#]]) + .run(); + p.cargo("clean -p b").cwd("b").run(); + p.cargo("run") + .cwd("b") + .with_stdout_data(str![[r#" +ftest on + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]` + +"#]]) + .run(); + + /* Build a/ package again. If we cache different feature dep builds correctly, + * this should not cause a rebuild of dep_crate */ + p.cargo("clean -p a").cwd("a").run(); + p.cargo("run") + .cwd("a") + .with_stdout_data(str![[r#" +ftest off + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]` + +"#]]) + .run(); + + /* Build b/ package again. If we cache different feature dep builds correctly, + * this should not cause a rebuild */ + p.cargo("clean -p b").cwd("b").run(); + p.cargo("run") + .cwd("b") + .with_stdout_data(str![[r#" +ftest on + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_bin_features_caches_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [features] + foo = [] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + let msg = if cfg!(feature = "foo") { "feature on" } else { "feature off" }; + println!("{}", msg); + } + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.rename_run("foo", "off1") + .with_stdout_data(str![[r#" +feature off + +"#]]) + .run(); + + p.cargo("build --features foo") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.rename_run("foo", "on1") + .with_stdout_data(str![[r#" +feature on + +"#]]) + .run(); + + /* Targets should be cached from the first build */ + + let mut e = p.cargo("build -v"); + + // MSVC does not include hash in binary filename, so it gets recompiled. + if cfg!(target_env = "msvc") { + e.with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } else { + e.with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } + e.run(); + p.rename_run("foo", "off2") + .with_stdout_data(str![[r#" +feature off + +"#]]) + .run(); + + let mut e = p.cargo("build --features foo -v"); + if cfg!(target_env = "msvc") { + e.with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } else { + e.with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } + e.run(); + p.rename_run("foo", "on2") + .with_stdout_data(str![[r#" +feature on + +"#]]) + .run(); +} + +#[cargo_test] +fn rebuild_tests_if_lib_changes() { + let p = project() + .file("src/lib.rs", "pub fn foo() {}") + .file("tests/foo-test.rs", "extern crate foo;") + .build(); + + p.cargo("build").run(); + p.cargo("test").run(); + + sleep_ms(1000); + p.change_file("src/lib.rs", ""); + + p.cargo("build").run(); + p.cargo("test -v --test foo-test") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency foo was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo_test [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo_test-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn no_rebuild_transitive_target_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + [dev-dependencies] + b = { path = "b" } + "#, + ) + .file("src/lib.rs", "") + .file("tests/foo.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.foo.dependencies] + c = { path = "../c" } + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + c = { path = "../c" } + "#, + ) + .file("b/src/lib.rs", "") + .file("c/Cargo.toml", &basic_manifest("c", "0.0.1")) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("test --no-run") + .with_stderr_data(str![[r#" +[COMPILING] c v0.0.1 ([ROOT]/foo/c) +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[EXECUTABLE] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test] +fn rerun_if_changed_in_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "a/build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + } + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn same_build_dir_cached_packages() { + let p = project() + .no_manifest() + .file( + "a1/Cargo.toml", + r#" + [package] + name = "a1" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + b = { path = "../b" } + "#, + ) + .file("a1/src/lib.rs", "") + .file( + "a2/Cargo.toml", + r#" + [package] + name = "a2" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + b = { path = "../b" } + "#, + ) + .file("a2/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + c = { path = "../c" } + "#, + ) + .file("b/src/lib.rs", "") + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + d = { path = "../d" } + "#, + ) + .file("c/src/lib.rs", "") + .file("d/Cargo.toml", &basic_manifest("d", "0.0.1")) + .file("d/src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "./target" + "#, + ) + .build(); + + p.cargo("build") + .cwd("a1") + .with_stderr_data(str![[r#" +[LOCKING] 3 packages to latest compatible versions +[COMPILING] d v0.0.1 ([ROOT]/foo/d) +[COMPILING] c v0.0.1 ([ROOT]/foo/c) +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[COMPILING] a1 v0.0.1 ([ROOT]/foo/a1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .cwd("a2") + .with_stderr_data(str![[r#" +[LOCKING] 3 packages to latest compatible versions +[COMPILING] a2 v0.0.1 ([ROOT]/foo/a2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn no_rebuild_if_build_artifacts_move_backwards_in_time() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + p.root().move_into_the_past(); + + p.cargo("build") + .with_stdout_data(str![]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rebuild_if_build_artifacts_move_forward_in_time() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + p.root().move_into_the_future(); + + p.cargo("build") + .env("CARGO_LOG", "") + .with_stdout_data(str![]) + .with_stderr_data(str![[r#" +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rebuild_if_environment_changes() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "old desc" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{}", env!("CARGO_PKG_DESCRIPTION")); + } + "#, + ) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +old desc + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "new desc" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ); + + p.cargo("run -v") + .with_stdout_data(str![[r#" +new desc + +"#]]) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the environment variable CARGO_PKG_DESCRIPTION changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn no_rebuild_when_rename_dir() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace] + + [dependencies] + foo = { path = "foo" } + "#, + ) + .file("src/_unused.rs", "") + .file("build.rs", "fn main() {}") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.0.1")) + .file("foo/src/lib.rs", "") + .file("foo/build.rs", "fn main() {}") + .build(); + + // make sure the most recently modified file is `src/lib.rs`, not + // `Cargo.toml`, to expose a historical bug where we forgot to strip the + // `Cargo.toml` path from looking for the package root. + cargo_test_support::sleep_ms(100); + fs::write(p.root().join("src/lib.rs"), "").unwrap(); + + p.cargo("build").run(); + let mut new = p.root(); + new.pop(); + new.push("bar"); + fs::rename(p.root(), &new).unwrap(); + + p.cargo("build") + .cwd(&new) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unused_optional_dep() { + Package::new("registry1", "0.1.0").publish(); + Package::new("registry2", "0.1.0").publish(); + Package::new("registry3", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "p" + authors = [] + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + baz = { path = "baz" } + registry1 = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + authors = [] + + [dev-dependencies] + registry2 = "*" + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + authors = [] + + [dependencies] + registry3 = { version = "*", optional = true } + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn path_dev_dep_registry_updates() { + Package::new("registry1", "0.1.0").publish(); + Package::new("registry2", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "p" + authors = [] + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + authors = [] + + [dependencies] + registry1 = "*" + + [dev-dependencies] + baz = { path = "../baz"} + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + authors = [] + + [dependencies] + registry2 = "*" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn change_panic_mode() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ['bar', 'baz'] + [profile.dev] + panic = 'abort' + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + + [dependencies] + bar = { path = '../bar' } + "#, + ) + .file("baz/src/lib.rs", "extern crate bar;") + .build(); + + p.cargo("build -p bar").run(); + p.cargo("build -p baz").run(); +} + +#[cargo_test] +fn dont_rebuild_based_on_plugins() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + + [workspace] + members = ['baz'] + + [dependencies] + proc-macro-thing = { path = 'proc-macro-thing' } + "#, + ) + .file("src/lib.rs", "") + .file( + "proc-macro-thing/Cargo.toml", + r#" + [package] + name = "proc-macro-thing" + version = "0.1.1" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + qux = { path = '../qux' } + "#, + ) + .file("proc-macro-thing/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + + [dependencies] + qux = { path = '../qux' } + "#, + ) + .file("baz/src/main.rs", "fn main() {}") + .file("qux/Cargo.toml", &basic_manifest("qux", "0.1.1")) + .file("qux/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build -p baz").run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -p bar") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn reuse_workspace_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + + [workspace] + + [dependencies] + baz = { path = 'baz' } + "#, + ) + .file("src/lib.rs", "") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.1")) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("test -p baz -v --no-run") + .with_stderr_data(str![[r#" +[COMPILING] baz v0.1.1 ([ROOT]/foo/baz) +[RUNNING] `rustc --crate-name baz [..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/baz-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn reuse_shared_build_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + shared = {path = "shared"} + + [workspace] + members = ["shared", "bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("shared/Cargo.toml", &basic_manifest("shared", "0.0.1")) + .file("shared/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + + [build-dependencies] + shared = { path = "../shared" } + "#, + ) + .file("bar/src/lib.rs", "") + .file("bar/build.rs", "fn main() {}") + .build(); + + p.cargo("build --workspace").run(); + // This should not recompile! + p.cargo("build -p foo -v") + .with_stderr_data(str![[r#" +[FRESH] shared v0.0.1 ([ROOT]/foo/shared) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_rustflags_is_cached() { + let p = project().file("src/lib.rs", "").build(); + + // This isn't ever cached, we always have to recompile + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -v") + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -v") + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_rustc_extra_flags_is_cached() { + let p = project().file("src/lib.rs", "").build(); + + // This isn't ever cached, we always have to recompile + p.cargo("rustc") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("rustc -v -- -C linker=cc") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("rustc -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("rustc -v -- -C linker=cc") + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn update_dependency_mtime_does_not_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build -Z mtime-on-use") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // This does not make new files, but it does update the mtime of the dependency. + p.cargo("build -p bar -Z mtime-on-use") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // This should not recompile! + p.cargo("build -Z mtime-on-use") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +fn fingerprint_cleaner(mut dir: PathBuf, timestamp: filetime::FileTime) { + // Cargo is experimenting with letting outside projects develop some + // limited forms of GC for target_dir. This is one of the forms. + // Specifically, Cargo is updating the mtime of a file in + // target/profile/.fingerprint each time it uses the fingerprint. + // So a cleaner can remove files associated with a fingerprint + // if all the files in the fingerprint's folder are older then a time stamp without + // effecting any builds that happened since that time stamp. + let mut cleaned = false; + dir.push(".fingerprint"); + for fing in fs::read_dir(&dir).unwrap() { + let fing = fing.unwrap(); + + let outdated = |f: io::Result| { + filetime::FileTime::from_last_modification_time(&f.unwrap().metadata().unwrap()) + <= timestamp + }; + if fs::read_dir(fing.path()).unwrap().all(outdated) { + fs::remove_dir_all(fing.path()).unwrap(); + println!("remove: {:?}", fing.path()); + // a real cleaner would remove the big files in deps and build as well + // but fingerprint is sufficient for our tests + cleaned = true; + } else { + } + } + assert!( + cleaned, + "called fingerprint_cleaner, but there was nothing to remove" + ); +} + +#[cargo_test] +fn fingerprint_cleaner_does_not_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [features] + a = [] + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build -Z mtime-on-use") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .run(); + p.cargo("build -Z mtime-on-use --features a") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + if is_coarse_mtime() { + sleep_ms(1000); + } + let timestamp = filetime::FileTime::from_system_time(SystemTime::now()); + if is_coarse_mtime() { + sleep_ms(1000); + } + // This does not make new files, but it does update the mtime. + p.cargo("build -Z mtime-on-use --features a") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + fingerprint_cleaner(p.target_debug_dir(), timestamp); + // This should not recompile! + p.cargo("build -Z mtime-on-use --features a") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // But this should be cleaned and so need a rebuild + p.cargo("build -Z mtime-on-use") + .masquerade_as_nightly_cargo(&["mtime-on-use"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn reuse_panic_build_dep_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [build-dependencies] + bar = { path = "bar" } + + [dev-dependencies] + bar = { path = "bar" } + + [profile.dev] + panic = "abort" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + // Check that `bar` is not built twice. It is only needed once (without `panic`). + p.cargo("test --lib --no-run -v") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..] +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]--test[..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn reuse_panic_pm() { + // foo(panic) -> bar(panic) + // somepm(nopanic) -> bar(nopanic) + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + somepm = { path = "somepm" } + + [profile.dev] + panic = "abort" + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .file( + "somepm/Cargo.toml", + r#" + [package] + name = "somepm" + version = "0.0.1" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + bar = { path = "../bar" } + "#, + ) + .file("somepm/src/lib.rs", "extern crate bar;") + .build(); + + // bar is built once without panic (for proc-macro) and once with (for the + // normal dependency). + p.cargo("build -v") + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..] -C panic=abort [..] +[RUNNING] `rustc --crate-name bar [..] +[COMPILING] somepm v0.0.1 ([ROOT]/foo/somepm) +[RUNNING] `rustc --crate-name somepm [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C panic=abort [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn bust_patched_dep() { + Package::new("registry1", "0.1.0").publish(); + Package::new("registry2", "0.1.0") + .dep("registry1", "0.1.0") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + registry2 = "0.1.0" + + [patch.crates-io] + registry1 = { path = "reg1new" } + "#, + ) + .file("src/lib.rs", "") + .file("reg1new/Cargo.toml", &basic_manifest("registry1", "0.1.0")) + .file("reg1new/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + if is_coarse_mtime() { + sleep_ms(1000); + } + + p.change_file("reg1new/src/lib.rs", "// modified"); + if is_coarse_mtime() { + sleep_ms(1000); + } + + p.cargo("build -v").with_stderr_data(str![[r#" +[DIRTY] registry1 v0.1.0 ([ROOT]/foo/reg1new): the file `reg1new/src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] registry1 v0.1.0 ([ROOT]/foo/reg1new) +[RUNNING] `rustc --crate-name registry1 [..] +[DIRTY] registry2 v0.1.0: the dependency registry1 was rebuilt +[COMPILING] registry2 v0.1.0 +[RUNNING] `rustc --crate-name registry2 [..] +[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency registry2 was rebuilt +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] registry1 v0.1.0 ([ROOT]/foo/reg1new) +[FRESH] registry2 v0.1.0 +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rebuild_on_mid_build_file_modification() { + let server = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = server.local_addr().unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["root", "proc_macro_dep"] + "#, + ) + .file( + "root/Cargo.toml", + r#" + [package] + name = "root" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + proc_macro_dep = { path = "../proc_macro_dep" } + "#, + ) + .file( + "root/src/lib.rs", + r#" + #[macro_use] + extern crate proc_macro_dep; + + #[derive(Noop)] + pub struct X; + "#, + ) + .file( + "proc_macro_dep/Cargo.toml", + r#" + [package] + name = "proc_macro_dep" + version = "0.1.0" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + "#, + ) + .file( + "proc_macro_dep/src/lib.rs", + &format!( + r#" + extern crate proc_macro; + + use std::io::Read; + use std::net::TcpStream; + use proc_macro::TokenStream; + + #[proc_macro_derive(Noop)] + pub fn noop(_input: TokenStream) -> TokenStream {{ + let mut stream = TcpStream::connect("{}").unwrap(); + let mut v = Vec::new(); + stream.read_to_end(&mut v).unwrap(); + "".parse().unwrap() + }} + "#, + addr + ), + ) + .build(); + let root = p.root(); + + let t = thread::spawn(move || { + let socket = server.accept().unwrap().0; + sleep_ms(1000); + let mut file = OpenOptions::new() + .write(true) + .append(true) + .open(root.join("root/src/lib.rs")) + .unwrap(); + writeln!(file, "// modified").expect("Failed to append to root sources"); + drop(file); + drop(socket); + drop(server.accept().unwrap()); + }); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep) +[COMPILING] root v0.1.0 ([ROOT]/foo/root) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -v").with_stderr_data(str![[r#" +[FRESH] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep) +[DIRTY] root v0.1.0 ([ROOT]/foo/root): the file `root/src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] root v0.1.0 ([ROOT]/foo/root) +[RUNNING] `rustc --crate-name root [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); + + t.join().ok().unwrap(); +} + +#[cargo_test] +fn dirty_both_lib_and_test() { + // This tests that all artifacts that depend on the results of a build + // script will get rebuilt when the build script reruns, even for separate + // commands. It does the following: + // + // 1. Project "foo" has a build script which will compile a small + // staticlib to link against. Normally this would use the `cc` crate, + // but here we just use rustc to avoid the `cc` dependency. + // 2. Build the library. + // 3. Build the unit test. The staticlib intentionally has a bad value. + // 4. Rewrite the staticlib with the correct value. + // 5. Build the library again. + // 6. Build the unit test. This should recompile. + + let slib = |n| { + format!( + r#" + #[no_mangle] + pub extern "C" fn doit() -> i32 {{ + return {}; + }} + "#, + n + ) + }; + + let p = project() + .file( + "src/lib.rs", + r#" + extern "C" { + fn doit() -> i32; + } + + #[test] + fn t1() { + assert_eq!(unsafe { doit() }, 1, "doit assert failure"); + } + "#, + ) + .file( + "build.rs", + r#" + use std::env; + use std::path::PathBuf; + use std::process::Command; + + fn main() { + let rustc = env::var_os("RUSTC").unwrap(); + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + assert!( + Command::new(rustc) + .args(&[ + "--crate-type=staticlib", + "--out-dir", + out_dir.to_str().unwrap(), + "slib.rs" + ]) + .status() + .unwrap() + .success(), + "slib build failed" + ); + println!("cargo::rustc-link-lib=slib"); + println!("cargo::rustc-link-search={}", out_dir.display()); + } + "#, + ) + .file("slib.rs", &slib(2)) + .build(); + + p.cargo("build").run(); + + // 2 != 1 + p.cargo("test --lib") + .with_status(101) + .with_stdout_data("...\n[..]doit assert failure[..]\n...") + .run(); + + if is_coarse_mtime() { + // #5918 + sleep_ms(1000); + } + // Fix the mistake. + p.change_file("slib.rs", &slib(1)); + + p.cargo("build").run(); + // This should recompile with the new static lib, and the test should pass. + p.cargo("test --lib").run(); +} + +#[cargo_test] +fn script_fails_stay_dirty() { + // Check if a script is aborted (such as hitting Ctrl-C) that it will re-run. + // Steps: + // 1. Build to establish fingerprints. + // 2. Make a change that triggers the build script to re-run. Abort the + // script while it is running. + // 3. Run the build again and make sure it re-runs the script. + let p = project() + .file( + "build.rs", + r#" + mod helper; + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + helper::doit(); + } + "#, + ) + .file("helper.rs", "pub fn doit() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("build").run(); + if is_coarse_mtime() { + sleep_ms(1000); + } + p.change_file("helper.rs", r#"pub fn doit() {panic!("Crash!");}"#); + p.cargo("build") + .with_stderr_data("...\n[..]Crash![..]\n...") + .with_status(101) + .run(); + // There was a bug where this second call would be "fresh". + p.cargo("build") + .with_stderr_data("...\n[..]Crash![..]\n...") + .with_status(101) + .run(); +} + +#[cargo_test] +fn simulated_docker_deps_stay_cached() { + // Test what happens in docker where the nanoseconds are zeroed out. + Package::new("regdep", "1.0.0").publish(); + Package::new("regdep_old_style", "1.0.0") + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .publish(); + Package::new("regdep_env", "1.0.0") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=SOMEVAR"); + } + "#, + ) + .file("src/lib.rs", "") + .publish(); + Package::new("regdep_rerun", "1.0.0") + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + } + "#, + ) + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + pathdep = { path = "pathdep" } + regdep = "1.0" + regdep_old_style = "1.0" + regdep_env = "1.0" + regdep_rerun = "1.0" + "#, + ) + .file( + "src/lib.rs", + " + extern crate pathdep; + extern crate regdep; + extern crate regdep_old_style; + extern crate regdep_env; + extern crate regdep_rerun; + ", + ) + .file("build.rs", "fn main() {}") + .file("pathdep/Cargo.toml", &basic_manifest("pathdep", "1.0.0")) + .file("pathdep/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + let already_zero = { + // This happens on HFS with 1-second timestamp resolution, + // or other filesystems where it just so happens to write exactly on a + // 1-second boundary. + let metadata = fs::metadata(p.root().join("src/lib.rs")).unwrap(); + let mtime = FileTime::from_last_modification_time(&metadata); + mtime.nanoseconds() == 0 + }; + + // Recursively remove `nanoseconds` from every path. + fn zeropath(path: &Path) { + for entry in walkdir::WalkDir::new(path) + .into_iter() + .filter_map(|e| e.ok()) + { + let metadata = fs::metadata(entry.path()).unwrap(); + let mtime = metadata.modified().unwrap(); + let mtime_duration = mtime.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let trunc_mtime = FileTime::from_unix_time(mtime_duration.as_secs() as i64, 0); + let atime = metadata.accessed().unwrap(); + let atime_duration = atime.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let trunc_atime = FileTime::from_unix_time(atime_duration.as_secs() as i64, 0); + if let Err(e) = filetime::set_file_times(entry.path(), trunc_atime, trunc_mtime) { + // Windows doesn't allow changing filetimes on some things + // (directories, other random things I'm not sure why). Just + // ignore them. + if e.kind() == std::io::ErrorKind::PermissionDenied { + println!("PermissionDenied filetime on {:?}", entry.path()); + } else { + panic!("FileTime error on {:?}: {:?}", entry.path(), e); + } + } + } + } + zeropath(&p.root()); + zeropath(&paths::home()); + + if already_zero { + println!("already zero"); + // If it was already truncated, then everything stays fresh. + p.cargo("build -v") + .with_stderr_data( + str![[r#" +[FRESH] pathdep [..] +[FRESH] regdep [..] +[FRESH] regdep_env [..] +[FRESH] regdep_old_style [..] +[FRESH] regdep_rerun [..] +[FRESH] foo [..] +[FINISHED] [..] + +"#]] + .unordered(), + ) + .run(); + } else { + println!("not already zero"); + // It is not ideal that `foo` gets recompiled, but that is the current + // behavior. Currently mtimes are ignored for registry deps. + // + // Note that this behavior is due to the fact that `foo` has a build + // script in "old" mode where it doesn't print `rerun-if-*`. In this + // mode we use `Precalculated` to fingerprint a path dependency, where + // `Precalculated` is an opaque string which has the most recent mtime + // in it. It differs between builds because one has nsec=0 and the other + // likely has a nonzero nsec. Hence, the rebuild. + p.cargo("build -v") + .with_stderr_data( + str![[r#" +[FRESH] regdep [..] +[FRESH] pathdep [..] +[FRESH] regdep_env [..] +[DIRTY] foo v0.1.0 ([ROOT]/foo): the precalculated components changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FRESH] regdep_rerun [..] +[FRESH] regdep_old_style [..] +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + } +} + +#[cargo_test] +fn metadata_change_invalidates() { + // (key, value, value-updated, env-var-name) + let scenarios = [ + ( + "description", + r#""foo""#, + r#""foo_updated""#, + "CARGO_PKG_DESCRIPTION", + ), + ( + "homepage", + r#""foo""#, + r#""foo_updated""#, + "CARGO_PKG_HOMEPAGE", + ), + ( + "repository", + r#""foo""#, + r#""foo_updated""#, + "CARGO_PKG_REPOSITORY", + ), + ( + "license", + r#""foo""#, + r#""foo_updated""#, + "CARGO_PKG_LICENSE", + ), + ( + "license-file", + r#""foo""#, + r#""foo_updated""#, + "CARGO_PKG_LICENSE_FILE", + ), + ( + "authors", + r#"["foo"]"#, + r#"["foo_updated"]"#, + "CARGO_PKG_AUTHORS", + ), + ( + "rust-version", + r#""1.0.0""#, + r#""1.0.1""#, + "CARGO_PKG_RUST_VERSION", + ), + ("readme", r#""foo""#, r#""foo_updated""#, "CARGO_PKG_README"), + ]; + let base_cargo_toml = r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#; + + let p = project().build(); + for (key, value, value_updated, env_var) in scenarios { + p.change_file("Cargo.toml", base_cargo_toml); + p.change_file( + "src/main.rs", + &format!( + r#" + fn main() {{ + let output = env!("{env_var}"); + println!("{{output}}"); + }} + "# + ), + ); + + // Compile the first time + p.cargo("build").run(); + + // Update the manifest, rebuild, and verify the build was invalided + p.change_file("Cargo.toml", &format!("{base_cargo_toml}\n{key} = {value}")); + p.cargo("build -v") + .with_stderr_data(format!( + r#"[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable {env_var} changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +"# + )) + .run(); + + // Remove references to the metadata and rebuild + p.change_file( + "src/main.rs", + r#" + fn main() { + println!("foo"); + } + "#, + ); + p.cargo("build").run(); + + // Update the manifest value and verify the build is NOT invalidated. + p.change_file( + "Cargo.toml", + &format!("{base_cargo_toml}\n{key} = {value_updated}"), + ); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + } +} + +#[cargo_test] +fn edition_change_invalidates() { + const MANIFEST: &str = r#" + [package] + name = "foo" + version = "0.1.0" + "#; + let p = project() + .file("Cargo.toml", MANIFEST) + .file("src/lib.rs", "") + .build(); + p.cargo("build").run(); + p.change_file("Cargo.toml", &format!("{}edition = \"2018\"", MANIFEST)); + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.change_file( + "Cargo.toml", + &format!( + r#"{}edition = "2018" + [lib] + edition = "2015" + "#, + MANIFEST + ), + ); + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rlib").count(), 1); +} + +#[cargo_test] +fn rename_with_path_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = 'a' } + "#, + ) + .file("src/lib.rs", "extern crate a; pub fn foo() { a::foo(); }") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + b = { path = 'b' } + "#, + ) + .file("a/src/lib.rs", "extern crate b; pub fn foo() { b::foo() }") + .file( + "a/b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + "#, + ) + .file("a/b/src/lib.rs", "pub fn foo() { }"); + let p = p.build(); + + p.cargo("build").run(); + + // Now rename the root directory and rerun `cargo run`. Not only should we + // not build anything but we also shouldn't crash. + let mut new = p.root(); + new.pop(); + new.push("foo2"); + + fs::rename(p.root(), &new).unwrap(); + + p.cargo("build") + .cwd(&new) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn move_target_directory_with_path_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "extern crate a; pub use a::print_msg;") + .file( + "a/build.rs", + r###" + use std::env; + use std::fs; + use std::path::Path; + + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("hello.rs"); + fs::write(&dest_path, r#" + pub fn message() -> &'static str { + "Hello, World!" + } + "#).unwrap(); + } + "###, + ) + .file( + "a/src/lib.rs", + r#" + include!(concat!(env!("OUT_DIR"), "/hello.rs")); + pub fn print_msg() { message(); } + "#, + ); + let p = p.build(); + + let mut parent = p.root(); + parent.pop(); + + p.cargo("build").run(); + + let new_target = p.root().join("target2"); + fs::rename(p.root().join("target"), &new_target).unwrap(); + + p.cargo("build") + .env("CARGO_TARGET_DIR", &new_target) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rerun_if_changes() { + let p = project() + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=FOO"); + if std::env::var("FOO").is_ok() { + println!("cargo::rerun-if-env-changed=BAR"); + } + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -v") + .env("FOO", "1") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .env("FOO", "1") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -v") + .env("FOO", "1") + .env("BAR", "1") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable BAR changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .env("FOO", "1") + .env("BAR", "1") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -v") + .env("BAR", "2") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .env("BAR", "2") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn channel_shares_filenames() { + // Test that different "nightly" releases use the same output filename. + + // Create separate rustc binaries to emulate running different toolchains. + let nightly1 = format!( + "\ +rustc 1.44.0-nightly (38114ff16 2020-03-21) +binary: rustc +commit-hash: 38114ff16e7856f98b2b4be7ab4cd29b38bed59a +commit-date: 2020-03-21 +host: {} +release: 1.44.0-nightly +LLVM version: 9.0 +", + rustc_host() + ); + + let nightly2 = format!( + "\ +rustc 1.44.0-nightly (a5b09d354 2020-03-31) +binary: rustc +commit-hash: a5b09d35473615e7142f5570f5c5fad0caf68bd2 +commit-date: 2020-03-31 +host: {} +release: 1.44.0-nightly +LLVM version: 9.0 +", + rustc_host() + ); + + let beta1 = format!( + "\ +rustc 1.43.0-beta.3 (4c587bbda 2020-03-25) +binary: rustc +commit-hash: 4c587bbda04ab55aaf56feab11dfdfe387a85d7a +commit-date: 2020-03-25 +host: {} +release: 1.43.0-beta.3 +LLVM version: 9.0 +", + rustc_host() + ); + + let beta2 = format!( + "\ +rustc 1.42.0-beta.5 (4e1c5f0e9 2020-02-28) +binary: rustc +commit-hash: 4e1c5f0e9769a588b91c977e3d81e140209ef3a2 +commit-date: 2020-02-28 +host: {} +release: 1.42.0-beta.5 +LLVM version: 9.0 +", + rustc_host() + ); + + let stable1 = format!( + "\ +rustc 1.42.0 (b8cedc004 2020-03-09) +binary: rustc +commit-hash: b8cedc00407a4c56a3bda1ed605c6fc166655447 +commit-date: 2020-03-09 +host: {} +release: 1.42.0 +LLVM version: 9.0 +", + rustc_host() + ); + + let stable2 = format!( + "\ +rustc 1.41.1 (f3e1a954d 2020-02-24) +binary: rustc +commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196 +commit-date: 2020-02-24 +host: {} +release: 1.41.1 +LLVM version: 9.0 +", + rustc_host() + ); + + let compiler = project() + .at("compiler") + .file("Cargo.toml", &basic_manifest("compiler", "0.1.0")) + .file( + "src/main.rs", + r#" + fn main() { + if std::env::args_os().any(|a| a == "-vV") { + print!("{}", env!("FUNKY_VERSION_TEST")); + return; + } + let mut cmd = std::process::Command::new("rustc"); + cmd.args(std::env::args_os().skip(1)); + assert!(cmd.status().unwrap().success()); + } + "#, + ) + .build(); + + let makeit = |version, vv| { + // Force a rebuild. + compiler.target_debug_dir().join("deps").rm_rf(); + compiler.cargo("build").env("FUNKY_VERSION_TEST", vv).run(); + fs::rename(compiler.bin("compiler"), compiler.bin(version)).unwrap(); + }; + makeit("nightly1", nightly1); + makeit("nightly2", nightly2); + makeit("beta1", beta1); + makeit("beta2", beta2); + makeit("stable1", stable1); + makeit("stable2", stable2); + + // Run `cargo check` with different rustc versions to observe its behavior. + let p = project().file("src/lib.rs", "").build(); + + // Runs `cargo check` and returns the rmeta filename created. + // Checks that the freshness matches the given value. + let check = |version, fresh| -> String { + let output = p + .cargo("check --message-format=json") + .env("RUSTC", compiler.bin(version)) + .run(); + // Collect the filenames generated. + let mut artifacts: Vec<_> = std::str::from_utf8(&output.stdout) + .unwrap() + .lines() + .filter_map(|line| { + let value: serde_json::Value = serde_json::from_str(line).unwrap(); + if value["reason"].as_str().unwrap() == "compiler-artifact" { + assert_eq!(value["fresh"].as_bool().unwrap(), fresh); + let filenames = value["filenames"].as_array().unwrap(); + assert_eq!(filenames.len(), 1); + Some(filenames[0].to_string()) + } else { + None + } + }) + .collect(); + // Should only generate one rmeta file. + assert_eq!(artifacts.len(), 1); + artifacts.pop().unwrap() + }; + + let nightly1_name = check("nightly1", false); + assert_eq!(check("nightly1", true), nightly1_name); + assert_eq!(check("nightly2", false), nightly1_name); // same as before + assert_eq!(check("nightly2", true), nightly1_name); + // Should rebuild going back to nightly1. + assert_eq!(check("nightly1", false), nightly1_name); + + let beta1_name = check("beta1", false); + assert_ne!(beta1_name, nightly1_name); + assert_eq!(check("beta1", true), beta1_name); + assert_eq!(check("beta2", false), beta1_name); // same as before + assert_eq!(check("beta2", true), beta1_name); + // Should rebuild going back to beta1. + assert_eq!(check("beta1", false), beta1_name); + + let stable1_name = check("stable1", false); + assert_ne!(stable1_name, nightly1_name); + assert_ne!(stable1_name, beta1_name); + let stable2_name = check("stable2", false); + assert_ne!(stable1_name, stable2_name); + // Check everything is fresh. + assert_eq!(check("stable1", true), stable1_name); + assert_eq!(check("stable2", true), stable2_name); + assert_eq!(check("beta1", true), beta1_name); + assert_eq!(check("nightly1", true), nightly1_name); +} + +#[cargo_test] +fn linking_interrupted() { + // Interrupt during the linking phase shouldn't leave test executable as "fresh". + + // This is used to detect when linking starts, then to pause the linker so + // that the test can kill cargo. + let link_listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let link_addr = link_listener.local_addr().unwrap(); + + // This is used to detect when rustc exits. + let rustc_listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let rustc_addr = rustc_listener.local_addr().unwrap(); + + // Create a linker that we can interrupt. + let linker = project() + .at("linker") + .file("Cargo.toml", &basic_manifest("linker", "1.0.0")) + .file( + "src/main.rs", + &r#" + fn main() { + // Figure out the output filename. + let output = match std::env::args().find(|a| a.starts_with("/OUT:")) { + Some(s) => s[5..].to_string(), + None => { + let mut args = std::env::args(); + loop { + if args.next().unwrap() == "-o" { + break; + } + } + args.next().unwrap() + } + }; + std::fs::remove_file(&output).unwrap(); + std::fs::write(&output, "").unwrap(); + // Tell the test that we are ready to be interrupted. + let mut socket = std::net::TcpStream::connect("__ADDR__").unwrap(); + // Wait for the test to kill us. + std::thread::sleep(std::time::Duration::new(60, 0)); + } + "# + .replace("__ADDR__", &link_addr.to_string()), + ) + .build(); + linker.cargo("build").run(); + + // Create a wrapper around rustc that will tell us when rustc is finished. + let rustc = project() + .at("rustc-waiter") + .file("Cargo.toml", &basic_manifest("rustc-waiter", "1.0.0")) + .file( + "src/main.rs", + &r#" + fn main() { + let mut conn = None; + // Check for a normal build (not -vV or --print). + if std::env::args().any(|arg| arg == "t1") { + // Tell the test that rustc has started. + conn = Some(std::net::TcpStream::connect("__ADDR__").unwrap()); + } + let status = std::process::Command::new("rustc") + .args(std::env::args().skip(1)) + .status() + .expect("rustc to run"); + std::process::exit(status.code().unwrap_or(1)); + } + "# + .replace("__ADDR__", &rustc_addr.to_string()), + ) + .build(); + rustc.cargo("build").run(); + + // Build it once so that the fingerprint gets saved to disk. + let p = project() + .file("src/lib.rs", "") + .file("tests/t1.rs", "") + .build(); + p.cargo("test --test t1 --no-run").run(); + + // Make a change, start a build, then interrupt it. + p.change_file("src/lib.rs", "// modified"); + let linker_env = format!("CARGO_TARGET_{}_LINKER", rustc_host_env()); + // NOTE: This assumes that the paths to the linker or rustc are not in the + // fingerprint. But maybe they should be? + let mut cmd = p + .cargo("test --test t1 --no-run") + .env(&linker_env, linker.bin("linker")) + .env("RUSTC", rustc.bin("rustc-waiter")) + .build_command(); + let mut child = cmd + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .env("__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE", "1") + .spawn() + .unwrap(); + // Wait for rustc to start. + let mut rustc_conn = rustc_listener.accept().unwrap().0; + // Wait for linking to start. + drop(link_listener.accept().unwrap()); + + // Interrupt the child. + death::ctrl_c(&mut child); + assert!(!child.wait().unwrap().success()); + // Wait for rustc to exit. If we don't wait, then the command below could + // start while rustc is still being torn down. + let mut buf = [0]; + drop(rustc_conn.read_exact(&mut buf)); + + // Build again, shouldn't be fresh. + p.cargo("test --test t1 -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[RUNNING] `rustc --crate-name t1 [..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/t1-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg_attr( + not(all(target_arch = "x86_64", target_os = "windows", target_env = "msvc")), + ignore +)] +fn lld_is_fresh() { + // Check for bug when using lld linker that it remains fresh with dylib. + let p = project() + .file( + ".cargo/config.toml", + r#" + [target.x86_64-pc-windows-msvc] + linker = "rust-lld" + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["dylib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("build -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn env_in_code_causes_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{:?}", option_env!("FOO")); + println!("{:?}", option_env!("FOO\nBAR")); + } + "#, + ) + .build(); + + p.cargo("build").env_remove("FOO").run(); + p.cargo("build") + .env_remove("FOO") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -v") + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -v") + .env("FOO", "baz") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .env("FOO", "baz") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -v") + .env_remove("FOO") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .env_remove("FOO") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let interesting = " #!$\nabc\r\\\t\u{8}\r\n"; + p.cargo("build").env("FOO", interesting).run(); + p.cargo("build") + .env("FOO", interesting) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build").env("FOO\nBAR", interesting).run(); + p.cargo("build") + .env("FOO\nBAR", interesting) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn env_build_script_no_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-env=FOO=bar"); + } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{:?}", env!("FOO")); + } + "#, + ) + .build(); + + p.cargo("build").run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_env_changes() { + // Checks that changes to the env var CARGO in the dep-info file triggers + // a rebuild. + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file( + "src/main.rs", + r#" + fn main() { + println!("{:?}", env!("CARGO")); + } + "#, + ) + .build(); + + let cargo_exe = cargo_test_support::cargo_exe(); + let other_cargo_path = p.root().join(cargo_exe.file_name().unwrap()); + std::fs::hard_link(&cargo_exe, &other_cargo_path).unwrap(); + let other_cargo = || { + let mut pb = cargo_test_support::process(&other_cargo_path); + pb.cwd(p.root()); + cargo_test_support::execs().with_process_builder(pb) + }; + + p.cargo("check").run(); + other_cargo() + .arg("check") + .arg("-v") + .with_stderr_data(str![[r#" +[DIRTY] foo v1.0.0 ([ROOT]/foo): the environment variable CARGO changed +[CHECKING] foo v1.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // And just to confirm that without using env! it doesn't rebuild. + p.change_file("src/main.rs", "fn main() {}"); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v1.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + other_cargo() + .arg("check") + .arg("-v") + .with_stderr_data(str![[r#" +[FRESH] foo v1.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn changing_linker() { + // Changing linker should rebuild. + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("build").run(); + let linker_env = format!("CARGO_TARGET_{}_LINKER", rustc_host_env()); + p.cargo("build --verbose") + .env(&linker_env, "nonexistent-linker") + .with_status(101) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C linker=nonexistent-linker [..]` +[ERROR] linker `nonexistent-linker` not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn verify_source_before_recompile() { + Package::new("bar", "0.1.0") + .file("src/lib.rs", "") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config").run(); + p.change_file( + ".cargo/config.toml", + r#" + [source.crates-io] + replace-with = 'vendor' + + [source.vendor] + directory = 'vendor' + "#, + ); + // Sanity check: vendoring works correctly. + p.cargo("check --verbose") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 +[RUNNING] `rustc --crate-name bar [..] [ROOT]/foo/vendor/bar/src/lib.rs [..] +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // Now modify vendored crate. + p.change_file( + "vendor/bar/src/lib.rs", + r#"compile_error!("You shall not pass!");"#, + ); + // Should ignore modified sources without any recompile. + p.cargo("check --verbose") + .with_stderr_data(str![[r#" +[FRESH] bar v0.1.0 +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Add a `RUSTFLAGS` to trigger a recompile. + // + // Cargo should refuse to build because of checksum verification failure. + // Cargo shouldn't recompile dependency `bar`. + p.cargo("check --verbose") + .env("RUSTFLAGS", "-W warnings") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the listed checksum of `[ROOT]/foo/vendor/bar/src/lib.rs` has changed: +expected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +actual: 66e843918c1d4ea8231af814f9f958958808249d4407de01114acb730ecd9bdf + +directory sources are not intended to be edited, if modifications are required then it is recommended that `[patch]` is used with a forked copy of the source + +"#]]) + .run(); +} + +#[cargo_test] +fn skip_mtime_check_in_selected_cargo_home_subdirs() { + let p = project() + .at("cargo_home/registry/foo") + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .build(); + let project_root = p.root(); + let cargo_home = project_root.parent().unwrap().parent().unwrap(); + p.cargo("check -v") + .env("CARGO_HOME", &cargo_home) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/registry/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.change_file("src/lib.rs", "illegal syntax"); + p.cargo("check -v") + .env("CARGO_HOME", &cargo_home) + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/cargo_home/registry/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn use_mtime_cache_in_cargo_home() { + let p = project() + .at("cargo_home/foo") + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .build(); + let project_root = p.root(); + let cargo_home = project_root.parent().unwrap(); + p.cargo("check -v") + .env("CARGO_HOME", &cargo_home) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.change_file("src/lib.rs", "illegal syntax"); + p.cargo("check -v") + .env("CARGO_HOME", &cargo_home) + .with_status(101) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/cargo_home/foo): the file `src/lib.rs` has changed ([TIME_DIFF_AFTER_LAST_BUILD]) +[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +... +[ERROR] could not compile `foo` (lib) due to 1 previous error +... +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness_checksum.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness_checksum.rs new file mode 100644 index 000000000..863153fe5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/freshness_checksum.rs @@ -0,0 +1,2963 @@ +//! Tests for checksum-based fingerprinting (rebuild detection). + +use std::fs::{self, OpenOptions}; +use std::io::prelude::*; +use std::net::TcpListener; +use std::process::Stdio; +use std::thread; + +use cargo_test_support::assert_deps_contains; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{ + basic_lib_manifest, basic_manifest, project, rustc_host, rustc_host_env, str, +}; + +use super::death; + +#[cargo_test] +fn non_nightly_fails() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("build -Zchecksum-freshness") + .with_stderr_data(str![[r#" +[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn checksum_actually_uses_checksum() { + let p = project() + .file("src/main.rs", "mod a; fn main() {}") + .file("src/a.rs", "") + .build(); + + p.cargo("check -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.root().move_into_the_future(); + + p.cargo("check -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn checksum_build_compatible_with_mtime_build() { + let p = project() + .file("src/main.rs", "mod a; fn main() {}") + .file("src/a.rs", "") + .build(); + + p.cargo("check -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn same_size_different_content() { + let p = project() + .file("src/main.rs", "mod a; fn main() {}") + .file("src/a.rs", "") + .build(); + + p.cargo("check -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.change_file("src/main.rs", "mod a;fn main() { }"); + + p.cargo("check -v -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/main.rs` has changed (checksum didn't match, blake3=26aa07e1adab787246f9d333be65d2eb78dd5fd0fee834ba7a769098b4b651bc != blake3=fc1a42e376d9c148227c13de41b77143f6b5b8132d2b204b63cdbc9326848894) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test( + nightly, + reason = "-Zbinary-dep-depinfo is unstable, also requires -Zchecksum-hash-algorithm" +)] +fn binary_depinfo_correctly_encoded() { + Package::new("regdep", "0.1.0") + .file("src/lib.rs", "pub fn f() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + regdep = "0.1" + bar = {path = "./bar"} + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + regdep::f(); + bar::f(); + } + "#, + ) + /*********** Path Dependency `bar` ***********/ + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn f() {}") + .build(); + + let host = rustc_host(); + p.cargo("build -Zbinary-dep-depinfo -Zchecksum-freshness --target") + .arg(&host) + .masquerade_as_nightly_cargo(&["binary-dep-depinfo", "checksum-freshness"]) + .with_stderr_data(str![[r#" +... +[COMPILING] foo v0.1.0 ([ROOT]/foo) +... + +"#]]) + .run(); + + assert_deps_contains( + &p, + &format!("target/{}/debug/.fingerprint/foo-*/dep-bin-foo", host), + &[ + (0, "src/main.rs"), + (1, &format!("{}/debug/deps/libbar-*.rlib", host)), + (1, &format!("{}/debug/deps/libregdep-*.rlib", host)), + ], + ); + + // Make sure it stays fresh. + p.cargo("build -Zbinary-dep-depinfo -Zchecksum-freshness --target") + .arg(&host) + .masquerade_as_nightly_cargo(&["binary-dep-depinfo", "checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn modifying_and_moving() { + let p = project() + .file("src/main.rs", "mod a; fn main() {}") + .file("src/a.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.root().move_into_the_past(); + p.root().join("target").move_into_the_past(); + + p.change_file("src/a.rs", "#[allow(unused)]fn main() {}"); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): file size changed (0 != 28) for `src/a.rs` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + fs::rename(&p.root().join("src/a.rs"), &p.root().join("src/b.rs")).unwrap(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +error[E0583]: file not found for module `a` +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn rebuild_sub_package_then_while_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [dependencies.a] + path = "a" + [dependencies.b] + path = "b" + "#, + ) + .file("src/lib.rs", "extern crate a; extern crate b;") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + authors = [] + version = "0.0.1" + edition = "2015" + [dependencies.b] + path = "../b" + "#, + ) + .file("a/src/lib.rs", "extern crate b;") + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file("b/src/lib.rs", "pub fn b() {}"); + + p.cargo("build -Zchecksum-freshness -pb -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[DIRTY] b v0.0.1 ([ROOT]/foo/b): file size changed (0 != 13) for `b/src/lib.rs` +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[RUNNING] `rustc --crate-name b [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + "src/lib.rs", + "extern crate a; extern crate b; pub fn toplevel() {}", + ); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] b v0.0.1 ([ROOT]/foo/b) +[DIRTY] a v0.0.1 ([ROOT]/foo/a): the dependency b was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name a [..] +[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency b was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn changing_lib_features_caches_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [features] + foo = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness --features foo") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + /* Targets should be cached from the first build */ + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness --features foo") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn changing_profiles_caches_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [profile.dev] + panic = "abort" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .run(); + + /* Targets should be cached from the first build */ + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test -Zchecksum-freshness foo") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn changing_bin_paths_common_target_features_caches_targets() { + // Make sure dep_cache crate is built once per feature + let p = project() + .no_manifest() + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "./target" + "#, + ) + .file( + "dep_crate/Cargo.toml", + r#" + [package] + name = "dep_crate" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + ftest = [] + "#, + ) + .file( + "dep_crate/src/lib.rs", + r#" + #[cfg(feature = "ftest")] + pub fn yo() { + println!("ftest on") + } + #[cfg(not(feature = "ftest"))] + pub fn yo() { + println!("ftest off") + } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + dep_crate = {path = "../dep_crate", features = []} + "#, + ) + .file("a/src/lib.rs", "") + .file( + "a/src/main.rs", + r#" + extern crate dep_crate; + use dep_crate::yo; + fn main() { + yo(); + } + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + dep_crate = {path = "../dep_crate", features = ["ftest"]} + "#, + ) + .file("b/src/lib.rs", "") + .file( + "b/src/main.rs", + r#" + extern crate dep_crate; + use dep_crate::yo; + fn main() { + yo(); + } + "#, + ) + .build(); + + /* Build and rebuild a/. Ensure dep_crate only builds once */ + p.cargo("run -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("a") + .with_stdout_data(str![[r#" +ftest off + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate) +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]` + +"#]]) + .run(); + p.cargo("clean -p a").cwd("a").run(); + p.cargo("run -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("a") + .with_stdout_data(str![[r#" +ftest off + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]` + +"#]]) + .run(); + + /* Build and rebuild b/. Ensure dep_crate only builds once */ + p.cargo("run -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("b") + .with_stdout_data(str![[r#" +ftest on + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] dep_crate v0.0.1 ([ROOT]/foo/dep_crate) +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]` + +"#]]) + .run(); + p.cargo("clean -p b").cwd("b").run(); + p.cargo("run -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("b") + .with_stdout_data(str![[r#" +ftest on + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]` + +"#]]) + .run(); + + /* Build a/ package again. If we cache different feature dep builds correctly, + * this should not cause a rebuild of dep_crate */ + p.cargo("clean -p a").cwd("a").run(); + p.cargo("run -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("a") + .with_stdout_data(str![[r#" +ftest off + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/a[EXE]` + +"#]]) + .run(); + + /* Build b/ package again. If we cache different feature dep builds correctly, + * this should not cause a rebuild */ + p.cargo("clean -p b").cwd("b").run(); + p.cargo("run -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("b") + .with_stdout_data(str![[r#" +ftest on + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/./target/debug/b[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn changing_bin_features_caches_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + edition = "2015" + + [features] + foo = [] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + let msg = if cfg!(feature = "foo") { "feature on" } else { "feature off" }; + println!("{}", msg); + } + "#, + ) + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.rename_run("foo", "off1") + .with_stdout_data(str![[r#" +feature off + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness --features foo") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.rename_run("foo", "on1") + .with_stdout_data(str![[r#" +feature on + +"#]]) + .run(); + + /* Targets should be cached from the first build */ + + let mut e = p.cargo("build -Zchecksum-freshness -v"); + e.masquerade_as_nightly_cargo(&["checksum-freshness"]); + + // MSVC does not include hash in binary filename, so it gets recompiled. + if cfg!(target_env = "msvc") { + e.with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } else { + e.with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } + e.run(); + p.rename_run("foo", "off2") + .with_stdout_data(str![[r#" +feature off + +"#]]) + .run(); + + let mut e = p.cargo("build -Zchecksum-freshness --features foo -v"); + e.masquerade_as_nightly_cargo(&["checksum-freshness"]); + if cfg!(target_env = "msvc") { + e.with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the list of features changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } else { + e.with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); + } + e.run(); + p.rename_run("foo", "on2") + .with_stdout_data(str![[r#" +feature on + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn rebuild_tests_if_lib_changes() { + let p = project() + .file("src/lib.rs", "pub fn foo() {}") + .file("tests/foo-test.rs", "extern crate foo;") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("test -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + p.change_file("src/lib.rs", ""); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("test -Zchecksum-freshness -v --test foo-test") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency foo was rebuilt ([TIME_DIFF_AFTER_LAST_BUILD]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo_test [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo_test-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn no_rebuild_transitive_target_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + [dev-dependencies] + b = { path = "b" } + "#, + ) + .file("src/lib.rs", "") + .file("tests/foo.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.foo.dependencies] + c = { path = "../c" } + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + c = { path = "../c" } + "#, + ) + .file("b/src/lib.rs", "") + .file("c/Cargo.toml", &basic_manifest("c", "0.0.1")) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("test -Zchecksum-freshness --no-run") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] c v0.0.1 ([ROOT]/foo/c) +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[EXECUTABLE] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn rerun_if_changed_in_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "a/build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + } + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn same_build_dir_cached_packages() { + let p = project() + .no_manifest() + .file( + "a1/Cargo.toml", + r#" + [package] + name = "a1" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + b = { path = "../b" } + "#, + ) + .file("a1/src/lib.rs", "") + .file( + "a2/Cargo.toml", + r#" + [package] + name = "a2" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + b = { path = "../b" } + "#, + ) + .file("a2/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + c = { path = "../c" } + "#, + ) + .file("b/src/lib.rs", "") + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + d = { path = "../d" } + "#, + ) + .file("c/src/lib.rs", "") + .file("d/Cargo.toml", &basic_manifest("d", "0.0.1")) + .file("d/src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = "./target" + "#, + ) + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("a1") + .with_stderr_data(str![[r#" +[LOCKING] 3 packages to latest compatible versions +[COMPILING] d v0.0.1 ([ROOT]/foo/d) +[COMPILING] c v0.0.1 ([ROOT]/foo/c) +[COMPILING] b v0.0.1 ([ROOT]/foo/b) +[COMPILING] a1 v0.0.1 ([ROOT]/foo/a1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd("a2") + .with_stderr_data(str![[r#" +[LOCKING] 3 packages to latest compatible versions +[COMPILING] a2 v0.0.1 ([ROOT]/foo/a2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn no_rebuild_if_build_artifacts_move_backwards_in_time() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + p.root().move_into_the_past(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stdout_data(str![]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn rebuild_if_environment_changes() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "old desc" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{}", env!("CARGO_PKG_DESCRIPTION")); + } + "#, + ) + .build(); + + p.cargo("run -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stdout_data(str![[r#" +old desc + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "new desc" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ); + + p.cargo("run -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stdout_data(str![[r#" +new desc + +"#]]) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the environment variable CARGO_PKG_DESCRIPTION changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn no_rebuild_when_rename_dir() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace] + + [dependencies] + foo = { path = "foo" } + "#, + ) + .file("src/_unused.rs", "") + .file("build.rs", "fn main() {}") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.0.1")) + .file("foo/src/lib.rs", "") + .file("foo/build.rs", "fn main() {}") + .build(); + + // make sure the most recently modified file is `src/lib.rs`, not + // `Cargo.toml`, to expose a historical bug where we forgot to strip the + // `Cargo.toml` path from looking for the package root. + fs::write(p.root().join("src/lib.rs"), "").unwrap(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + let mut new = p.root(); + new.pop(); + new.push("bar"); + fs::rename(p.root(), &new).unwrap(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd(&new) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn unused_optional_dep() { + Package::new("registry1", "0.1.0").publish(); + Package::new("registry2", "0.1.0").publish(); + Package::new("registry3", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "p" + authors = [] + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + baz = { path = "baz" } + registry1 = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + authors = [] + + [dev-dependencies] + registry2 = "*" + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + authors = [] + + [dependencies] + registry3 = { version = "*", optional = true } + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn path_dev_dep_registry_updates() { + Package::new("registry1", "0.1.0").publish(); + Package::new("registry2", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "p" + authors = [] + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + authors = [] + + [dependencies] + registry1 = "*" + + [dev-dependencies] + baz = { path = "../baz"} + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + authors = [] + + [dependencies] + registry2 = "*" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn change_panic_mode() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ['bar', 'baz'] + [profile.dev] + panic = 'abort' + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + + [dependencies] + bar = { path = '../bar' } + "#, + ) + .file("baz/src/lib.rs", "extern crate bar;") + .build(); + + p.cargo("build -Zchecksum-freshness -p bar") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness -p baz") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn dont_rebuild_based_on_plugins() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + + [workspace] + members = ['baz'] + + [dependencies] + proc-macro-thing = { path = 'proc-macro-thing' } + "#, + ) + .file("src/lib.rs", "") + .file( + "proc-macro-thing/Cargo.toml", + r#" + [package] + name = "proc-macro-thing" + version = "0.1.1" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + qux = { path = '../qux' } + "#, + ) + .file("proc-macro-thing/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + + [dependencies] + qux = { path = '../qux' } + "#, + ) + .file("baz/src/main.rs", "fn main() {}") + .file("qux/Cargo.toml", &basic_manifest("qux", "0.1.1")) + .file("qux/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness -p baz") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness -p bar") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn reuse_workspace_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.1" + edition = "2015" + + [workspace] + + [dependencies] + baz = { path = 'baz' } + "#, + ) + .file("src/lib.rs", "") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.1")) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("test -Zchecksum-freshness -p baz -v --no-run") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] baz v0.1.1 ([ROOT]/foo/baz) +[RUNNING] `rustc --crate-name baz [..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/baz-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn reuse_shared_build_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + shared = {path = "shared"} + + [workspace] + members = ["shared", "bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("shared/Cargo.toml", &basic_manifest("shared", "0.0.1")) + .file("shared/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + + [build-dependencies] + shared = { path = "../shared" } + "#, + ) + .file("bar/src/lib.rs", "") + .file("bar/build.rs", "fn main() {}") + .build(); + + p.cargo("build -Zchecksum-freshness --workspace") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + // This should not recompile! + p.cargo("build -Zchecksum-freshness -p foo -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] shared v0.0.1 ([ROOT]/foo/shared) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn changing_rustflags_is_cached() { + let p = project().file("src/lib.rs", "").build(); + + // This isn't ever cached, we always have to recompile + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("RUSTFLAGS", "-C linker=cc") + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn changing_rustc_extra_flags_is_cached() { + let p = project().file("src/lib.rs", "").build(); + + // This isn't ever cached, we always have to recompile + p.cargo("rustc -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("rustc -Zchecksum-freshness -v -- -C linker=cc") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("rustc -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("rustc -Zchecksum-freshness -v -- -C linker=cc") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn reuse_panic_build_dep_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [build-dependencies] + bar = { path = "bar" } + + [dev-dependencies] + bar = { path = "bar" } + + [profile.dev] + panic = "abort" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + // Check that `bar` is not built twice. It is only needed once (without `panic`). + p.cargo("test -Zchecksum-freshness --lib --no-run -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..] +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..]--test[..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn reuse_panic_pm() { + // foo(panic) -> bar(panic) + // somepm(nopanic) -> bar(nopanic) + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + somepm = { path = "somepm" } + + [profile.dev] + panic = "abort" + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .file( + "somepm/Cargo.toml", + r#" + [package] + name = "somepm" + version = "0.0.1" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + bar = { path = "../bar" } + "#, + ) + .file("somepm/src/lib.rs", "extern crate bar;") + .build(); + + // bar is built once without panic (for proc-macro) and once with (for the + // normal dependency). + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..] -C panic=abort [..] +[RUNNING] `rustc --crate-name bar [..] +[COMPILING] somepm v0.0.1 ([ROOT]/foo/somepm) +[RUNNING] `rustc --crate-name somepm [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C panic=abort [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn bust_patched_dep() { + Package::new("registry1", "0.1.0").publish(); + Package::new("registry2", "0.1.0") + .dep("registry1", "0.1.0") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + registry2 = "0.1.0" + + [patch.crates-io] + registry1 = { path = "reg1new" } + "#, + ) + .file("src/lib.rs", "") + .file("reg1new/Cargo.toml", &basic_manifest("registry1", "0.1.0")) + .file("reg1new/src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + p.change_file("reg1new/src/lib.rs", "// modified"); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[DIRTY] registry1 v0.1.0 ([ROOT]/foo/reg1new): file size changed (0 != 11) for `reg1new/src/lib.rs` +[COMPILING] registry1 v0.1.0 ([ROOT]/foo/reg1new) +[RUNNING] `rustc --crate-name registry1 [..] +[DIRTY] registry2 v0.1.0: the dependency registry1 was rebuilt +[COMPILING] registry2 v0.1.0 +[RUNNING] `rustc --crate-name registry2 [..] +[DIRTY] foo v0.0.1 ([ROOT]/foo): the dependency registry2 was rebuilt +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] registry1 v0.1.0 ([ROOT]/foo/reg1new) +[FRESH] registry2 v0.1.0 +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn rebuild_on_mid_build_file_modification() { + let server = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = server.local_addr().unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["root", "proc_macro_dep"] + "#, + ) + .file( + "root/Cargo.toml", + r#" + [package] + name = "root" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + proc_macro_dep = { path = "../proc_macro_dep" } + "#, + ) + .file( + "root/src/lib.rs", + r#" + #[macro_use] + extern crate proc_macro_dep; + + #[derive(Noop)] + pub struct X; + "#, + ) + .file( + "proc_macro_dep/Cargo.toml", + r#" + [package] + name = "proc_macro_dep" + version = "0.1.0" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + "#, + ) + .file( + "proc_macro_dep/src/lib.rs", + &format!( + r#" + extern crate proc_macro; + + use std::io::Read; + use std::net::TcpStream; + use proc_macro::TokenStream; + + #[proc_macro_derive(Noop)] + pub fn noop(_input: TokenStream) -> TokenStream {{ + let mut stream = TcpStream::connect("{}").unwrap(); + let mut v = Vec::new(); + stream.read_to_end(&mut v).unwrap(); + "".parse().unwrap() + }} + "#, + addr + ), + ) + .build(); + let root = p.root(); + + let t = thread::spawn(move || { + let socket = server.accept().unwrap().0; + let mut file = OpenOptions::new() + .write(true) + .append(true) + .open(root.join("root/src/lib.rs")) + .unwrap(); + writeln!(file, "// modified").expect("Failed to append to root sources"); + drop(file); + drop(socket); + drop(server.accept().unwrap()); + }); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep) +[COMPILING] root v0.1.0 ([ROOT]/foo/root) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] proc_macro_dep v0.1.0 ([ROOT]/foo/proc_macro_dep) +[DIRTY] root v0.1.0 ([ROOT]/foo/root): file size changed (150 != 162) for `root/src/lib.rs` +[COMPILING] root v0.1.0 ([ROOT]/foo/root) +[RUNNING] `rustc --crate-name root [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + t.join().ok().unwrap(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn dirty_both_lib_and_test() { + // This tests that all artifacts that depend on the results of a build + // script will get rebuilt when the build script reruns, even for separate + // commands. It does the following: + // + // 1. Project "foo" has a build script which will compile a small + // staticlib to link against. Normally this would use the `cc` crate, + // but here we just use rustc to avoid the `cc` dependency. + // 2. Build the library. + // 3. Build the unit test. The staticlib intentionally has a bad value. + // 4. Rewrite the staticlib with the correct value. + // 5. Build the library again. + // 6. Build the unit test. This should recompile. + + let slib = |n| { + format!( + r#" + #[no_mangle] + pub extern "C" fn doit() -> i32 {{ + return {}; + }} + "#, + n + ) + }; + + let p = project() + .file( + "src/lib.rs", + r#" + extern "C" { + fn doit() -> i32; + } + + #[test] + fn t1() { + assert_eq!(unsafe { doit() }, 1, "doit assert failure"); + } + "#, + ) + .file( + "build.rs", + r#" + use std::env; + use std::path::PathBuf; + use std::process::Command; + + fn main() { + let rustc = env::var_os("RUSTC").unwrap(); + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + assert!( + Command::new(rustc) + .args(&[ + "--crate-type=staticlib", + "--out-dir", + out_dir.to_str().unwrap(), + "slib.rs" + ]) + .status() + .unwrap() + .success(), + "slib build failed" + ); + println!("cargo::rustc-link-lib=slib"); + println!("cargo::rustc-link-search={}", out_dir.display()); + } + "#, + ) + .file("slib.rs", &slib(2)) + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + // 2 != 1 + p.cargo("test -Zchecksum-freshness --lib") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_status(101) + .with_stdout_data("...\n[..]doit assert failure[..]\n...") + .run(); + + // Fix the mistake. + p.change_file("slib.rs", &slib(1)); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + // This should recompile with the new static lib, and the test should pass. + p.cargo("test -Zchecksum-freshness --lib") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn script_fails_stay_dirty() { + // Check if a script is aborted (such as hitting Ctrl-C) that it will re-run. + // Steps: + // 1. Build to establish fingerprints. + // 2. Make a change that triggers the build script to re-run. Abort the + // script while it is running. + // 3. Run the build again and make sure it re-runs the script. + let p = project() + .file( + "build.rs", + r#" + mod helper; + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + helper::doit(); + } + "#, + ) + .file("helper.rs", "pub fn doit() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.change_file("helper.rs", r#"pub fn doit() {panic!("Crash!");}"#); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data("...\n[..]Crash![..]\n...") + .with_status(101) + .run(); + // There was a bug where this second call would be "fresh". + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data("...\n[..]Crash![..]\n...") + .with_status(101) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn edition_change_invalidates() { + const MANIFEST: &str = r#" + [package] + name = "foo" + version = "0.1.0" + "#; + let p = project() + .file("Cargo.toml", MANIFEST) + .file("src/lib.rs", "") + .build(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.change_file("Cargo.toml", &format!("{}edition = \"2018\"", MANIFEST)); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.change_file( + "Cargo.toml", + &format!( + r#"{}edition = "2018" + [lib] + edition = "2015" + "#, + MANIFEST + ), + ); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_eq!(p.glob("target/debug/deps/libfoo-*.rlib").count(), 1); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn rename_with_path_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = 'a' } + "#, + ) + .file("src/lib.rs", "extern crate a; pub fn foo() { a::foo(); }") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + b = { path = 'b' } + "#, + ) + .file("a/src/lib.rs", "extern crate b; pub fn foo() { b::foo() }") + .file( + "a/b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + "#, + ) + .file("a/b/src/lib.rs", "pub fn foo() { }"); + let p = p.build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + // Now rename the root directory and rerun `cargo run`. Not only should we + // not build anything but we also shouldn't crash. + let mut new = p.root(); + new.pop(); + new.push("foo2"); + + fs::rename(p.root(), &new).unwrap(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .cwd(&new) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn move_target_directory_with_path_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "extern crate a; pub use a::print_msg;") + .file( + "a/build.rs", + r###" + use std::env; + use std::fs; + use std::path::Path; + + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("hello.rs"); + fs::write(&dest_path, r#" + pub fn message() -> &'static str { + "Hello, World!" + } + "#).unwrap(); + } + "###, + ) + .file( + "a/src/lib.rs", + r#" + include!(concat!(env!("OUT_DIR"), "/hello.rs")); + pub fn print_msg() { message(); } + "#, + ); + let p = p.build(); + + let mut parent = p.root(); + parent.pop(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + let new_target = p.root().join("target2"); + fs::rename(p.root().join("target"), &new_target).unwrap(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("CARGO_TARGET_DIR", &new_target) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn rerun_if_changes() { + let p = project() + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-env-changed=FOO"); + if std::env::var("FOO").is_ok() { + println!("cargo::rerun-if-env-changed=BAR"); + } + } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "1") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "1") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "1") + .env("BAR", "1") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable BAR changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "1") + .env("BAR", "1") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("BAR", "2") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the env variable FOO changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("BAR", "2") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn channel_shares_filenames() { + // Test that different "nightly" releases use the same output filename. + + // Create separate rustc binaries to emulate running different toolchains. + let nightly1 = format!( + "\ +rustc 1.44.0-nightly (38114ff16 2020-03-21) +binary: rustc +commit-hash: 38114ff16e7856f98b2b4be7ab4cd29b38bed59a +commit-date: 2020-03-21 +host: {} +release: 1.44.0-nightly +LLVM version: 9.0 +", + rustc_host() + ); + + let nightly2 = format!( + "\ +rustc 1.44.0-nightly (a5b09d354 2020-03-31) +binary: rustc +commit-hash: a5b09d35473615e7142f5570f5c5fad0caf68bd2 +commit-date: 2020-03-31 +host: {} +release: 1.44.0-nightly +LLVM version: 9.0 +", + rustc_host() + ); + + let beta1 = format!( + "\ +rustc 1.43.0-beta.3 (4c587bbda 2020-03-25) +binary: rustc +commit-hash: 4c587bbda04ab55aaf56feab11dfdfe387a85d7a +commit-date: 2020-03-25 +host: {} +release: 1.43.0-beta.3 +LLVM version: 9.0 +", + rustc_host() + ); + + let beta2 = format!( + "\ +rustc 1.42.0-beta.5 (4e1c5f0e9 2020-02-28) +binary: rustc +commit-hash: 4e1c5f0e9769a588b91c977e3d81e140209ef3a2 +commit-date: 2020-02-28 +host: {} +release: 1.42.0-beta.5 +LLVM version: 9.0 +", + rustc_host() + ); + + let stable1 = format!( + "\ +rustc 1.42.0 (b8cedc004 2020-03-09) +binary: rustc +commit-hash: b8cedc00407a4c56a3bda1ed605c6fc166655447 +commit-date: 2020-03-09 +host: {} +release: 1.42.0 +LLVM version: 9.0 +", + rustc_host() + ); + + let stable2 = format!( + "\ +rustc 1.41.1 (f3e1a954d 2020-02-24) +binary: rustc +commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196 +commit-date: 2020-02-24 +host: {} +release: 1.41.1 +LLVM version: 9.0 +", + rustc_host() + ); + + let compiler = project() + .at("compiler") + .file("Cargo.toml", &basic_manifest("compiler", "0.1.0")) + .file( + "src/main.rs", + r#" + fn main() { + if std::env::args_os().any(|a| a == "-vV") { + print!("{}", env!("FUNKY_VERSION_TEST")); + return; + } + let mut cmd = std::process::Command::new("rustc"); + cmd.args(std::env::args_os().skip(1)); + assert!(cmd.status().unwrap().success()); + } + "#, + ) + .build(); + + let makeit = |version, vv| { + // Force a rebuild. + compiler.target_debug_dir().join("deps").rm_rf(); + compiler + .cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FUNKY_VERSION_TEST", vv) + .run(); + fs::rename(compiler.bin("compiler"), compiler.bin(version)).unwrap(); + }; + makeit("nightly1", nightly1); + makeit("nightly2", nightly2); + makeit("beta1", beta1); + makeit("beta2", beta2); + makeit("stable1", stable1); + makeit("stable2", stable2); + + // Run `cargo check` with different rustc versions to observe its behavior. + let p = project().file("src/lib.rs", "").build(); + + // Runs `cargo check` and returns the rmeta filename created. + // Checks that the freshness matches the given value. + let check = |version, fresh| -> String { + let output = p + .cargo("check -Zchecksum-freshness --message-format=json") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("RUSTC", compiler.bin(version)) + .run(); + // Collect the filenames generated. + let mut artifacts: Vec<_> = std::str::from_utf8(&output.stdout) + .unwrap() + .lines() + .filter_map(|line| { + let value: serde_json::Value = serde_json::from_str(line).unwrap(); + if value["reason"].as_str().unwrap() == "compiler-artifact" { + assert_eq!(value["fresh"].as_bool().unwrap(), fresh); + let filenames = value["filenames"].as_array().unwrap(); + assert_eq!(filenames.len(), 1); + Some(filenames[0].to_string()) + } else { + None + } + }) + .collect(); + // Should only generate one rmeta file. + assert_eq!(artifacts.len(), 1); + artifacts.pop().unwrap() + }; + + let nightly1_name = check("nightly1", false); + assert_eq!(check("nightly1", true), nightly1_name); + assert_eq!(check("nightly2", false), nightly1_name); // same as before + assert_eq!(check("nightly2", true), nightly1_name); + // Should rebuild going back to nightly1. + assert_eq!(check("nightly1", false), nightly1_name); + + let beta1_name = check("beta1", false); + assert_ne!(beta1_name, nightly1_name); + assert_eq!(check("beta1", true), beta1_name); + assert_eq!(check("beta2", false), beta1_name); // same as before + assert_eq!(check("beta2", true), beta1_name); + // Should rebuild going back to beta1. + assert_eq!(check("beta1", false), beta1_name); + + let stable1_name = check("stable1", false); + assert_ne!(stable1_name, nightly1_name); + assert_ne!(stable1_name, beta1_name); + let stable2_name = check("stable2", false); + assert_ne!(stable1_name, stable2_name); + // Check everything is fresh. + assert_eq!(check("stable1", true), stable1_name); + assert_eq!(check("stable2", true), stable2_name); + assert_eq!(check("beta1", true), beta1_name); + assert_eq!(check("nightly1", true), nightly1_name); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn linking_interrupted() { + // Interrupt during the linking phase shouldn't leave test executable as "fresh". + + // This is used to detect when linking starts, then to pause the linker so + // that the test can kill cargo. + let link_listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let link_addr = link_listener.local_addr().unwrap(); + + // This is used to detect when rustc exits. + let rustc_listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let rustc_addr = rustc_listener.local_addr().unwrap(); + + // Create a linker that we can interrupt. + let linker = project() + .at("linker") + .file("Cargo.toml", &basic_manifest("linker", "1.0.0")) + .file( + "src/main.rs", + &r#" + fn main() { + // Figure out the output filename. + let output = match std::env::args().find(|a| a.starts_with("/OUT:")) { + Some(s) => s[5..].to_string(), + None => { + let mut args = std::env::args(); + loop { + if args.next().unwrap() == "-o" { + break; + } + } + args.next().unwrap() + } + }; + std::fs::remove_file(&output).unwrap(); + std::fs::write(&output, "").unwrap(); + // Tell the test that we are ready to be interrupted. + let mut socket = std::net::TcpStream::connect("__ADDR__").unwrap(); + // Wait for the test to kill us. + std::thread::sleep(std::time::Duration::new(60, 0)); + } + "# + .replace("__ADDR__", &link_addr.to_string()), + ) + .build(); + linker + .cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + // Create a wrapper around rustc that will tell us when rustc is finished. + let rustc = project() + .at("rustc-waiter") + .file("Cargo.toml", &basic_manifest("rustc-waiter", "1.0.0")) + .file( + "src/main.rs", + &r#" + fn main() { + let mut conn = None; + // Check for a normal build (not -vV or --print). + if std::env::args().any(|arg| arg == "t1") { + // Tell the test that rustc has started. + conn = Some(std::net::TcpStream::connect("__ADDR__").unwrap()); + } + let status = std::process::Command::new("rustc") + .args(std::env::args().skip(1)) + .status() + .expect("rustc to run"); + std::process::exit(status.code().unwrap_or(1)); + } + "# + .replace("__ADDR__", &rustc_addr.to_string()), + ) + .build(); + rustc + .cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + // Build it once so that the fingerprint gets saved to disk. + let p = project() + .file("src/lib.rs", "") + .file("tests/t1.rs", "") + .build(); + p.cargo("test -Zchecksum-freshness --test t1 --no-run") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + + // Make a change, start a build, then interrupt it. + p.change_file("src/lib.rs", "// modified"); + let linker_env = format!("CARGO_TARGET_{}_LINKER", rustc_host_env()); + // NOTE: This assumes that the paths to the linker or rustc are not in the + // fingerprint. But maybe they should be? + let mut cmd = p + .cargo("test -Zchecksum-freshness --test t1 --no-run") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env(&linker_env, linker.bin("linker")) + .env("RUSTC", rustc.bin("rustc-waiter")) + .build_command(); + let mut child = cmd + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .env("__CARGO_TEST_SETSID_PLEASE_DONT_USE_ELSEWHERE", "1") + .spawn() + .unwrap(); + // Wait for rustc to start. + let mut rustc_conn = rustc_listener.accept().unwrap().0; + // Wait for linking to start. + drop(link_listener.accept().unwrap()); + + // Interrupt the child. + death::ctrl_c(&mut child); + assert!(!child.wait().unwrap().success()); + // Wait for rustc to exit. If we don't wait, then the command below could + // start while rustc is still being torn down. + let mut buf = [0]; + drop(rustc_conn.read_exact(&mut buf)); + + // Build again, shouldn't be fresh. + p.cargo("test -Zchecksum-freshness --test t1 -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] +[RUNNING] `rustc --crate-name t1 [..] +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/t1-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +#[cfg(all(target_arch = "x86_64", target_os = "windows", target_env = "msvc"))] +fn lld_is_fresh() { + // Check for bug when using lld linker that it remains fresh with dylib. + let p = project() + .file( + ".cargo/config.toml", + r#" + [target.x86_64-pc-windows-msvc] + linker = "rust-lld" + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["dylib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn env_in_code_causes_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{:?}", option_env!("FOO")); + println!("{:?}", option_env!("FOO\nBAR")); + } + "#, + ) + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env_remove("FOO") + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env_remove("FOO") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "baz") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", "baz") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env_remove("FOO") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.1.0 ([ROOT]/foo): the environment variable FOO changed +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env_remove("FOO") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let interesting = " #!$\nabc\r\\\t\u{8}\r\n"; + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", interesting) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO", interesting) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO\nBAR", interesting) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("FOO\nBAR", interesting) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn env_build_script_no_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rustc-env=FOO=bar"); + } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{:?}", env!("FOO")); + } + "#, + ) + .build(); + + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn changing_linker() { + // Changing linker should rebuild. + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("build -Zchecksum-freshness") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .run(); + let linker_env = format!("CARGO_TARGET_{}_LINKER", rustc_host_env()); + p.cargo("build -Zchecksum-freshness --verbose") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env(&linker_env, "nonexistent-linker") + .with_status(101) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the config settings changed +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C linker=nonexistent-linker [..]` +[ERROR] linker `nonexistent-linker` not found +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn verify_source_before_recompile() { + Package::new("bar", "0.1.0") + .file("src/lib.rs", "") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config").run(); + p.change_file( + ".cargo/config.toml", + r#" + [source.crates-io] + replace-with = 'vendor' + + [source.vendor] + directory = 'vendor' + "#, + ); + // Sanity check: vendoring works correctly. + p.cargo("check -Zchecksum-freshness --verbose") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 +[RUNNING] `rustc --crate-name bar [..] [ROOT]/foo/vendor/bar/src/lib.rs [..] +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // Now modify vendored crate. + p.change_file( + "vendor/bar/src/lib.rs", + r#"compile_error!("You shall not pass!");"#, + ); + // Should ignore modified sources without any recompile. + p.cargo("check -Zchecksum-freshness --verbose") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .with_stderr_data(str![[r#" +[FRESH] bar v0.1.0 +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Add a `RUSTFLAGS` to trigger a recompile. + // + // Cargo should refuse to build because of checksum verification failure. + // Cargo shouldn't recompile dependency `bar`. + p.cargo("check -Zchecksum-freshness --verbose") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("RUSTFLAGS", "-W warnings") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the listed checksum of `[ROOT]/foo/vendor/bar/src/lib.rs` has changed: +expected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +actual: 66e843918c1d4ea8231af814f9f958958808249d4407de01114acb730ecd9bdf + +directory sources are not intended to be edited, if modifications are required then it is recommended that `[patch]` is used with a forked copy of the source + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn skip_checksum_check_in_selected_cargo_home_subdirs() { + let p = project() + .at("cargo_home/registry/foo") + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .build(); + let project_root = p.root(); + let cargo_home = project_root.parent().unwrap().parent().unwrap(); + p.cargo("check -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("CARGO_HOME", &cargo_home) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/registry/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.change_file("src/lib.rs", "illegal syntax"); + p.cargo("check -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("CARGO_HOME", &cargo_home) + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/cargo_home/registry/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "requires -Zchecksum-hash-algorithm")] +fn use_checksum_cache_in_cargo_home() { + let p = project() + .at("cargo_home/foo") + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .build(); + let project_root = p.root(); + let cargo_home = project_root.parent().unwrap(); + p.cargo("check -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("CARGO_HOME", &cargo_home) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.change_file("src/lib.rs", "illegal syntax"); + p.cargo("check -Zchecksum-freshness -v") + .masquerade_as_nightly_cargo(&["checksum-freshness"]) + .env("CARGO_HOME", &cargo_home) + .with_status(101) + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/cargo_home/foo): file size changed (0 != 14) for `src/lib.rs` +[CHECKING] foo v0.5.0 ([ROOT]/cargo_home/foo) +[RUNNING] `rustc --crate-name foo [..] src/lib.rs [..] +... +[ERROR] could not compile `foo` (lib) due to 1 previous error +... +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/future_incompat_report.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/future_incompat_report.rs new file mode 100644 index 000000000..bb4e6dbec --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/future_incompat_report.rs @@ -0,0 +1,453 @@ +//! Tests for future-incompat-report messages +//! +//! Note that these tests use the -Zfuture-incompat-test for rustc. +//! This causes rustc to treat *every* lint as future-incompatible. +//! This is done because future-incompatible lints are inherently +//! ephemeral, but we don't want to continually update these tests. +//! So we pick some random lint that will likely always be the same +//! over time. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_manifest, project, str, Project}; + +use super::config::write_config_toml; + +// An arbitrary lint (unused_variables) that triggers a lint. +// We use a special flag to force it to generate a report. +const FUTURE_EXAMPLE: &'static str = "fn main() { let x = 1; }"; +// Some text that will be displayed when the lint fires. +const FUTURE_OUTPUT: &'static str = "[..]unused variable[..]"; + +fn simple_project() -> Project { + project() + .file("Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file("src/main.rs", FUTURE_EXAMPLE) + .build() +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn output_on_stable() { + let p = simple_project(); + + p.cargo("check") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data(str![[r#" +... +[WARNING] unused variable: `x` +... +[NOTE] to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1` + +"#]]) + .run(); +} + +// This feature is stable, and should not be gated +#[cargo_test] +fn no_gate_future_incompat_report() { + let p = simple_project(); + + p.cargo("check --future-incompat-report") + .with_status(0) + .run(); + + p.cargo("report future-incompatibilities --id foo") + .with_stderr_data(str![[r#" +[ERROR] no reports are currently available + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn test_zero_future_incompat() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + // No note if --future-incompat-report is not specified. + p.cargo("check") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check --future-incompat-report") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[NOTE] 0 dependencies had future-incompatible warnings + +"#]]) + .run(); +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn test_single_crate() { + let p = simple_project(); + + for command in &["build", "check", "rustc", "test"] { + let check_has_future_compat = || { + p.cargo(command) + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data("\ +... +[WARNING] unused variable: `x` +... +[WARNING] the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 ([ROOT]/foo) +... +") + .with_stderr_does_not_contain("[..]incompatibility[..]") + .run(); + }; + + // Check that we show a message with no [future-incompat-report] config section + write_config_toml(""); + check_has_future_compat(); + + // Check that we show a message with `frequency = "always"` + write_config_toml( + "\ +[future-incompat-report] +frequency = 'always' +", + ); + check_has_future_compat(); + + // Check that we do not show a message with `frequency = "never"` + write_config_toml( + "\ +[future-incompat-report] +frequency = 'never' +", + ); + p.cargo(command) + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data( + "\ +[WARNING] unused variable: `x` +... +", + ) + .with_stderr_does_not_contain("[..]rejected[..]") + .with_stderr_does_not_contain("[..]incompatibility[..]") + .run(); + + // Check that passing `--future-incompat-report` overrides `frequency = 'never'` + p.cargo(command).arg("--future-incompat-report") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data("\ +[WARNING] unused variable: `x` +... +[WARNING] the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 ([ROOT]/foo) +... + - foo@0.0.0 +... +") + .run(); + } +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn test_multi_crate() { + Package::new("first-dep", "0.0.1") + .file("src/lib.rs", FUTURE_EXAMPLE) + .publish(); + Package::new("second-dep", "0.0.2") + .file("src/lib.rs", FUTURE_EXAMPLE) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + + [dependencies] + first-dep = "*" + second-dep = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + for command in &["build", "check", "rustc", "test"] { + p.cargo(command) + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_does_not_contain(FUTURE_OUTPUT) + .with_stderr_data("\ +... +[WARNING] the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2 +... +") + // Check that we don't have the 'triggers' message shown at the bottom of this loop, + // and that we don't explain how to show a per-package report + .with_stderr_does_not_contain("[..]triggers[..]") + .with_stderr_does_not_contain("[..]--package[..]") + .with_stderr_does_not_contain("[..]-p[..]") + .run(); + + p.cargo(command).arg("--future-incompat-report") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data("\ +... +[WARNING] the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2 +... + - first-dep@0.0.1 +... + - second-dep@0.0.2 +... +") + .run(); + + p.cargo("report future-incompatibilities") + .arg("--package") + .arg("first-dep@0.0.1") + .with_stdout_data( + "\ +... +The package `first-dep v0.0.1` currently triggers the following future incompatibility lints: +> [WARNING] unused variable: `x` +... +", + ) + .with_stdout_does_not_contain("[..]second-dep-0.0.2/src[..]") + .run(); + + p.cargo("report future-incompatibilities") + .arg("--package") + .arg("second-dep@0.0.2") + .with_stdout_data( + "\ +... +The package `second-dep v0.0.2` currently triggers the following future incompatibility lints: +> [WARNING] unused variable: `x` +... +", + ) + .with_stdout_does_not_contain("[..]first-dep-0.0.1/src[..]") + .run(); + } + + // Test that passing the correct id via '--id' doesn't generate a warning message + let output = p + .cargo("check") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .run(); + + // Extract the 'id' from the stdout. We are looking + // for the id in a line of the form "run `cargo report future-incompatibilities --id yZ7S`" + // which is generated by Cargo to tell the user what command to run + // This is just to test that passing the id suppresses the warning mesasge. Any users needing + // access to the report from a shell script should use the `--future-incompat-report` flag + let stderr = std::str::from_utf8(&output.stderr).unwrap(); + + // Find '--id ' in the output + let mut iter = stderr.split(' '); + iter.find(|w| *w == "--id").unwrap(); + let id = iter + .next() + .unwrap_or_else(|| panic!("Unexpected output:\n{}", stderr)); + // Strip off the trailing '`' included in the output + let id: String = id.chars().take_while(|c| *c != '`').collect(); + + p.cargo(&format!("report future-incompatibilities --id {}", id)) + .with_stdout_data(str![[r#" +... +The package `first-dep v0.0.1` currently triggers the following future incompatibility lints: +... +The package `second-dep v0.0.2` currently triggers the following future incompatibility lints: +... +"#]]) + .run(); + + // Test without --id, and also the full output of the report. + let output = p.cargo("report future-incompat").run(); + let output = std::str::from_utf8(&output.stdout).unwrap(); + assert!(output.starts_with("The following warnings were discovered")); + let mut lines = output + .lines() + // Skip the beginning of the per-package information. + .skip_while(|line| !line.starts_with("The package")); + for expected in &["first-dep v0.0.1", "second-dep v0.0.2"] { + assert_eq!( + &format!( + "The package `{}` currently triggers the following future incompatibility lints:", + expected + ), + lines.next().unwrap(), + "Bad output:\n{}", + output + ); + let mut count = 0; + while let Some(line) = lines.next() { + if line.is_empty() { + break; + } + count += 1; + } + assert!(count > 0); + } + assert_eq!(lines.next(), None); +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn color() { + let p = simple_project(); + + p.cargo("check") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .masquerade_as_nightly_cargo(&["future-incompat-test"]) + .run(); + + p.cargo("report future-incompatibilities") + .with_stdout_does_not_contain("[..]\x1b[[..]") + .run(); + + p.cargo("report future-incompatibilities") + .env("CARGO_TERM_COLOR", "always") + .with_stdout_contains("[..]\x1b[[..]") + .run(); +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn bad_ids() { + let p = simple_project(); + + p.cargo("report future-incompatibilities --id 1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no reports are currently available + +"#]]) + .run(); + + p.cargo("check") + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .masquerade_as_nightly_cargo(&["future-incompat-test"]) + .run(); + + p.cargo("report future-incompatibilities --id foo") + .with_status(1) + .with_stderr_data(str![ + "[ERROR] Invalid value: could not parse `foo` as a number" + ]) + .run(); + + p.cargo("report future-incompatibilities --id 7") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not find report with ID 7 +Available IDs are: 1 + +"#]]) + .run(); +} + +#[cargo_test( + nightly, + reason = "-Zfuture-incompat-test requires nightly (permanently)" +)] +fn suggestions_for_updates() { + Package::new("with_updates", "1.0.0") + .file("src/lib.rs", FUTURE_EXAMPLE) + .publish(); + Package::new("big_update", "1.0.0") + .file("src/lib.rs", FUTURE_EXAMPLE) + .publish(); + Package::new("without_updates", "1.0.0") + .file("src/lib.rs", FUTURE_EXAMPLE) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + with_updates = "1" + big_update = "1" + without_updates = "1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + Package::new("with_updates", "1.0.1") + .file("src/lib.rs", "") + .publish(); + Package::new("with_updates", "1.0.2") + .file("src/lib.rs", "") + .publish(); + Package::new("with_updates", "3.0.1") + .file("src/lib.rs", "") + .publish(); + Package::new("big_update", "2.0.0") + .file("src/lib.rs", "") + .publish(); + + // This is a hack to force cargo to update the index. Cargo can't do this + // automatically because doing a network update on every build would be a + // bad idea. Under normal circumstances, we'll hope the user has done + // something else along the way to trigger an update (building some other + // 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 without_updates").run(); + + p.cargo("check --future-incompat-report") + .masquerade_as_nightly_cargo(&["future-incompat-test"]) + .env("RUSTFLAGS", "-Zfuture-incompat-test") + .with_stderr_data(str![[r#" +... +- Some affected dependencies have newer versions available. +You may want to consider updating them to a newer version to see if the issue has been fixed. + +big_update v1.0.0 has the following newer versions available: 2.0.0 +with_updates v1.0.0 has the following newer versions available: 1.0.1, 1.0.2, 3.0.1 +... +"#]]) + .run(); + + p.cargo("report future-incompatibilities") + .with_stdout_data(str![[r#" +... +- Some affected dependencies have newer versions available. +You may want to consider updating them to a newer version to see if the issue has been fixed. + +big_update v1.0.0 has the following newer versions available: 2.0.0 +with_updates v1.0.0 has the following newer versions available: 1.0.1, 1.0.2, 3.0.1 +... +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/generate_lockfile.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/generate_lockfile.rs new file mode 100644 index 000000000..640cf5dc5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/generate_lockfile.rs @@ -0,0 +1,286 @@ +//! Tests for the `cargo generate-lockfile` command. + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Package, RegistryBuilder}; +use cargo_test_support::{basic_manifest, paths, project, str, ProjectBuilder}; + +#[cargo_test] +fn adding_and_removing_packages() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + let lock1 = p.read_lockfile(); + + // add a dep + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies.bar] + path = "bar" + "#, + ); + p.cargo("generate-lockfile").run(); + let lock2 = p.read_lockfile(); + assert_ne!(lock1, lock2); + + // change the dep + p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.0.2")); + p.cargo("generate-lockfile").run(); + let lock3 = p.read_lockfile(); + assert_ne!(lock1, lock3); + assert_ne!(lock2, lock3); + + // remove the dep + println!("lock4"); + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + "#, + ); + p.cargo("generate-lockfile").run(); + let lock4 = p.read_lockfile(); + assert_eq!(lock1, lock4); +} + +#[cargo_test] +fn no_index_update_sparse() { + let _registry = RegistryBuilder::new().http_index().build(); + no_index_update( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version + +"#]], + str![[r#" +[LOCKING] 1 package to latest compatible version + +"#]], + ); +} + +#[cargo_test] +fn no_index_update_git() { + no_index_update( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version + +"#]], + str![[r#" +[LOCKING] 1 package to latest compatible version + +"#]], + ); +} + +fn no_index_update(expected: impl IntoData, expected_unstable_option: impl IntoData) { + Package::new("serde", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies] + serde = "1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile") + .with_stderr_data(expected) + .run(); + + p.cargo("generate-lockfile -Zno-index-update") + .masquerade_as_nightly_cargo(&["no-index-update"]) + .with_stdout_data("") + .with_stderr_data(expected_unstable_option) + .run(); +} + +#[cargo_test] +fn preserve_metadata() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + let metadata = r#" +[metadata] +bar = "baz" +foo = "bar" +"#; + let lock = p.read_lockfile(); + let data = lock + metadata; + p.change_file("Cargo.lock", &data); + + // Build and make sure the metadata is still there + p.cargo("build").run(); + let lock = p.read_lockfile(); + assert!(lock.contains(metadata.trim()), "{}", lock); + + // Update and make sure the metadata is still there + p.cargo("update").run(); + let lock = p.read_lockfile(); + assert!(lock.contains(metadata.trim()), "{}", lock); +} + +#[cargo_test] +fn preserve_line_endings_issue_2076() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + let lockfile = p.root().join("Cargo.lock"); + p.cargo("generate-lockfile").run(); + assert!(lockfile.is_file()); + p.cargo("generate-lockfile").run(); + + let lock0 = p.read_lockfile(); + + assert!(lock0.starts_with("# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n")); + + let lock1 = lock0.replace("\n", "\r\n"); + p.change_file("Cargo.lock", &lock1); + + p.cargo("generate-lockfile").run(); + + let lock2 = p.read_lockfile(); + + assert!(lock2.starts_with("# This file is automatically @generated by Cargo.\r\n# It is not intended for manual editing.\r\n")); + assert_eq!(lock1, lock2); +} + +#[cargo_test] +fn cargo_update_generate_lockfile() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + let lockfile = p.root().join("Cargo.lock"); + assert!(!lockfile.is_file()); + p.cargo("update").with_stderr_data("").run(); + assert!(lockfile.is_file()); + + fs::remove_file(p.root().join("Cargo.lock")).unwrap(); + + assert!(!lockfile.is_file()); + p.cargo("update").with_stderr_data("").run(); + assert!(lockfile.is_file()); +} + +#[cargo_test] +fn duplicate_entries_in_lockfile() { + let _a = ProjectBuilder::new(paths::root().join("a")) + .file( + "Cargo.toml", + r#" + [package] + name = "a" + authors = [] + version = "0.0.1" + + [dependencies] + common = {path="common"} + "#, + ) + .file("src/lib.rs", "") + .build(); + + let common_toml = &basic_manifest("common", "0.0.1"); + + let _common_in_a = ProjectBuilder::new(paths::root().join("a/common")) + .file("Cargo.toml", common_toml) + .file("src/lib.rs", "") + .build(); + + let b = ProjectBuilder::new(paths::root().join("b")) + .file( + "Cargo.toml", + r#" + [package] + name = "b" + authors = [] + version = "0.0.1" + edition = "2015" + + [dependencies] + common = {path="common"} + a = {path="../a"} + "#, + ) + .file("src/lib.rs", "") + .build(); + + let _common_in_b = ProjectBuilder::new(paths::root().join("b/common")) + .file("Cargo.toml", common_toml) + .file("src/lib.rs", "") + .build(); + + // should fail due to a duplicate package `common` in the lock file + b.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package collision in the lockfile: packages common v0.0.1 ([ROOT]/a/common) and common v0.0.1 ([ROOT]/b/common) are different, but only one can be written to lockfile unambiguously + +"#]]) + .run(); +} + +#[cargo_test] +fn generate_lockfile_holds_lock_and_offline() { + Package::new("syn", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + + [dependencies] + syn = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); + + p.cargo("generate-lockfile --offline") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git.rs new file mode 100644 index 000000000..8d00ecf18 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git.rs @@ -0,0 +1,4262 @@ +//! Tests for git support. + +use std::fs; +use std::io::prelude::*; +use std::net::{TcpListener, TcpStream}; +use std::path::Path; +use std::str; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use std::thread; + +use cargo_test_support::git::{add_submodule, cargo_uses_gitoxide}; +use cargo_test_support::paths; +use cargo_test_support::prelude::IntoData; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_lib_manifest, basic_manifest, git, main_file, project}; +use cargo_test_support::{sleep_ms, str, t, Project}; + +#[cargo_test] +fn cargo_compile_simple_git_dep() { + let project = project(); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file( + "src/dep1.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + }); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + project + .cargo("build") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(project.bin("foo").is_file()); + + project + .process(&project.bin("foo")) + .with_stdout_data(str![[r#" +hello world + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_git_dep_branch() { + let project = project(); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file( + "src/dep1.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + }); + + // Make a new branch based on the current HEAD commit + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let head = repo.head().unwrap().target().unwrap(); + let head = repo.find_commit(head).unwrap(); + repo.branch("branchy", &head, true).unwrap(); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + git = '{}' + branch = "branchy" + + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + project + .cargo("build") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1?branch=branchy#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(project.bin("foo").is_file()); + + project + .process(&project.bin("foo")) + .with_stdout_data(str![[r#" +hello world + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_git_dep_tag() { + let project = project(); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file( + "src/dep1.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + }); + + // Make a tag corresponding to the current HEAD + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let head = repo.head().unwrap().target().unwrap(); + repo.tag( + "v0.1.0", + &repo.find_object(head, None).unwrap(), + &repo.signature().unwrap(), + "make a new tag", + false, + ) + .unwrap(); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + git = '{}' + tag = "v0.1.0" + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + project + .cargo("build") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1?tag=v0.1.0#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(project.bin("foo").is_file()); + + project + .process(&project.bin("foo")) + .with_stdout_data(str![[r#" +hello world + +"#]]) + .run(); + + project.cargo("build").run(); +} + +#[cargo_test] +fn cargo_compile_git_dep_pull_request() { + let project = project(); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file( + "src/dep1.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + }); + + // Make a reference in GitHub's pull request ref naming convention. + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let oid = repo.refname_to_id("HEAD").unwrap(); + let force = false; + let log_message = "open pull request"; + repo.reference("refs/pull/330/head", oid, force, log_message) + .unwrap(); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [dependencies] + dep1 = {{ git = "{}", rev = "refs/pull/330/head" }} + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + project + .cargo("build") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1?rev=refs%2Fpull%2F330%2Fhead#[..]) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(project.bin("foo").is_file()); +} + +#[cargo_test] +fn cargo_compile_with_nested_paths() { + let git_project = git::new("dep1", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + + name = "dep1" + version = "0.5.0" + edition = "2015" + authors = ["carlhuda@example.com"] + + [dependencies.dep2] + + version = "0.5.0" + path = "vendor/dep2" + + [lib] + + name = "dep1" + "#, + ) + .file( + "src/dep1.rs", + r#" + extern crate dep2; + + pub fn hello() -> &'static str { + dep2::hello() + } + "#, + ) + .file("vendor/dep2/Cargo.toml", &basic_lib_manifest("dep2")) + .file( + "vendor/dep2/src/dep2.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + version = "0.5.0" + git = '{}' + + [[bin]] + + name = "foo" + "#, + git_project.url() + ), + ) + .file( + "src/foo.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +hello world + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_malformed_nested_paths() { + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file( + "src/dep1.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + .file("vendor/dep2/Cargo.toml", "!INVALID!") + .file( + "vendor/dep3/Cargo.toml", + r#" + [package] + name = "dep3" + version = "0.5.0" + edition = "2015" + [dependencies] + subdep1 = { path = "../require-extra-build-step" } + "#, + ) + .file("vendor/dep3/src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + version = "0.5.0" + git = '{}' + + [[bin]] + + name = "foo" + "#, + git_project.url() + ), + ) + .file( + "src/foo.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +hello world + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_meta_package() { + let git_project = git::new("meta-dep", |project| { + project + .file("dep1/Cargo.toml", &basic_lib_manifest("dep1")) + .file( + "dep1/src/dep1.rs", + r#" + pub fn hello() -> &'static str { + "this is dep1" + } + "#, + ) + .file("dep2/Cargo.toml", &basic_lib_manifest("dep2")) + .file( + "dep2/src/dep2.rs", + r#" + pub fn hello() -> &'static str { + "this is dep2" + } + "#, + ) + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + version = "0.5.0" + git = '{}' + + [dependencies.dep2] + + version = "0.5.0" + git = '{}' + + [[bin]] + + name = "foo" + "#, + git_project.url(), + git_project.url() + ), + ) + .file( + "src/foo.rs", + &main_file( + r#""{} {}", dep1::hello(), dep2::hello()"#, + &["dep1", "dep2"], + ), + ) + .build(); + + p.cargo("build").run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +this is dep1 this is dep2 + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_short_ssh_git() { + let url = "git@github.com:a/dep"; + let well_formed_url = "ssh://git@github.com/a/dep"; + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep] + + git = "{}" + + [[bin]] + + name = "foo" + "#, + url + ), + ) + .file( + "src/foo.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(&format!( + "\ +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + invalid url `{}`: relative URL without a base; try using `{}` instead +", + url, well_formed_url + )) + .run(); +} + +#[cargo_test] +fn recompilation() { + let git_project = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("bar")) + .file("src/bar.rs", "pub fn bar() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + + version = "0.5.0" + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", &main_file(r#""{:?}", bar::bar()"#, &["bar"])) + .build(); + + // First time around we should compile both foo and bar + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Don't recompile the second time + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Modify a file manually, shouldn't trigger a recompile + git_project.change_file("src/bar.rs", r#"pub fn bar() { println!("hello!"); }"#); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("update") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 0 packages to latest compatible versions + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // 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); + + println!("compile after commit"); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.root().move_into_the_past(); + + // Update the dependency and carry on! + p.cargo("update") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..] + +"#]]) + .run(); + println!("going for the last compile"); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Make sure clean only cleans one dep + p.cargo("clean -p foo") + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn update_with_shared_deps() { + let git_project = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("bar")) + .file("src/bar.rs", "pub fn bar() {}") + }); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + path = "dep1" + [dependencies.dep2] + path = "dep2" + "#, + ) + .file( + "src/main.rs", + r#" + #[allow(unused_extern_crates)] + extern crate dep1; + #[allow(unused_extern_crates)] + extern crate dep2; + fn main() {} + "#, + ) + .file( + "dep1/Cargo.toml", + &format!( + r#" + [package] + name = "dep1" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + version = "0.5.0" + git = '{}' + "#, + git_project.url() + ), + ) + .file("dep1/src/lib.rs", "") + .file( + "dep2/Cargo.toml", + &format!( + r#" + [package] + name = "dep2" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + version = "0.5.0" + git = '{}' + "#, + git_project.url() + ), + ) + .file("dep2/src/lib.rs", "") + .build(); + + // First time around we should compile both foo and bar + p.cargo("check") + .with_stderr_data( + str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 3 packages to latest compatible versions +[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[CHECKING] dep1 v0.5.0 ([ROOT]/foo/dep1) +[CHECKING] dep2 v0.5.0 ([ROOT]/foo/dep2) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + // Modify a file manually, and commit it + git_project.change_file("src/bar.rs", r#"pub fn bar() { println!("hello!"); }"#); + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let old_head = repo.head().unwrap().target().unwrap(); + git::add(&repo); + git::commit(&repo); + + sleep_ms(1000); + + // By default, not transitive updates + println!("dep1 update"); + p.cargo("update dep1") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..] + +"#]]) + .run(); + + // Don't do anything bad on a weird --precise argument + println!("bar bad precise update"); + p.cargo("update bar --precise 0.1.2") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[ERROR] Unable to update [ROOTURL]/bar#0.1.2 + +Caused by: + revspec '0.1.2' not found; class=Reference (4); code=NotFound (-3) + +"#]]) + .run(); + + // 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 bar --precise") + .arg(&old_head.to_string()) + .with_stderr_data(str![[r#" +[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..] + +"#]]) + .run(); + + // Updating recursively should, however, update the repo. + println!("dep1 recursive update"); + p.cargo("update dep1 --recursive") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.5.0 ([ROOTURL]/bar#[..]) -> #[..] + +"#]]) + .run(); + + // Make sure we still only compile one version of the git repo + println!("build"); + p.cargo("check") + .with_stderr_data( + str![[r#" +[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[CHECKING] dep1 v0.5.0 ([ROOT]/foo/dep1) +[CHECKING] dep2 v0.5.0 ([ROOT]/foo/dep2) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + // We should be able to update transitive deps + p.cargo("update bar") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 0 packages to latest compatible versions + +"#]]) + .run(); +} + +#[cargo_test] +fn dep_with_submodule() { + let project = project(); + let git_project = git::new("dep1", |project| { + project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + }); + let git_project2 = git::new("dep2", |project| project.file("lib.rs", "pub fn dep() {}")); + + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let url = git_project2.root().to_url().to_string(); + git::add_submodule(&repo, &url, Path::new("src")); + git::commit(&repo); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/lib.rs", + "extern crate dep1; pub fn foo() { dep1::dep() }", + ) + .build(); + + project + .cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[UPDATING] git submodule `[ROOTURL]/dep2` +[LOCKING] 1 package to latest compatible version +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn dep_with_relative_submodule() { + let foo = project(); + let base = git::new("base", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "base" + version = "0.5.0" + edition = "2015" + + [dependencies] + deployment.path = "deployment" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn dep() { + deployment::deployment_func(); + } + "#, + ) + }); + let _deployment = git::new("deployment", |project| { + project + .file("src/lib.rs", "pub fn deployment_func() {}") + .file("Cargo.toml", &basic_lib_manifest("deployment")) + }); + + let base_repo = git2::Repository::open(&base.root()).unwrap(); + git::add_submodule(&base_repo, "../deployment", Path::new("deployment")); + git::commit(&base_repo); + + let project = foo + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.base] + git = '{}' + "#, + base.url() + ), + ) + .file("src/lib.rs", "pub fn foo() { }") + .build(); + + project + .cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/base` +[UPDATING] git submodule `[ROOTURL]/deployment` +[LOCKING] 2 packages to latest compatible versions +[CHECKING] deployment v0.5.0 ([ROOTURL]/base#[..]) +[CHECKING] base v0.5.0 ([ROOTURL]/base#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn dep_with_bad_submodule() { + let project = project(); + let git_project = git::new("dep1", |project| { + project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + }); + let git_project2 = git::new("dep2", |project| project.file("lib.rs", "pub fn dep() {}")); + + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let url = git_project2.root().to_url().to_string(); + git::add_submodule(&repo, &url, Path::new("src")); + git::commit(&repo); + + // now amend the first commit on git_project2 to make submodule ref point to not-found + // commit + let repo = git2::Repository::open(&git_project2.root()).unwrap(); + let original_submodule_ref = repo.refname_to_id("refs/heads/master").unwrap(); + let commit = repo.find_commit(original_submodule_ref).unwrap(); + commit + .amend( + Some("refs/heads/master"), + None, + None, + None, + Some("something something"), + None, + ) + .unwrap(); + + let p = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/lib.rs", + "extern crate dep1; pub fn foo() { dep1::dep() }", + ) + .build(); + + let expected = str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[UPDATING] git submodule `[ROOTURL]/dep2` +[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `dep1` + +Caused by: + Unable to update [ROOTURL]/dep1 + +Caused by: + failed to update submodule `src` + +Caused by: + object not found - no match for id ([..]); class=Odb (9); code=NotFound (-3) + +"#]]; + + p.cargo("check") + .with_stderr_data(expected) + .with_status(101) + .run(); +} + +#[cargo_test] +fn dep_with_skipped_submodule() { + // Ensure we skip dependency submodules if their update strategy is `none`. + let qux = git::new("qux", |project| { + project.no_manifest().file("README", "skip me") + }); + + let bar = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.0.0")) + .file("src/lib.rs", "") + }); + + // `qux` is a submodule of `bar`, but we don't want to update it. + let repo = git2::Repository::open(&bar.root()).unwrap(); + git::add_submodule(&repo, qux.url().as_str(), Path::new("qux")); + + let mut conf = git2::Config::open(&bar.root().join(".gitmodules")).unwrap(); + conf.set_str("submodule.qux.update", "none").unwrap(); + + git::add(&repo); + git::commit(&repo); + + let foo = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "{}" + "#, + bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[SKIPPING] git submodule `[ROOTURL]/qux` due to update strategy in .gitmodules +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.0.0 ([ROOTURL]/bar#[..]) +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn ambiguous_published_deps() { + let project = project(); + let git_project = git::new("dep", |project| { + project + .file( + "duplicate1/Cargo.toml", + &format!( + r#" + [package] + name = "duplicate" + version = "0.5.0" + edition = "2015" + publish = true + "# + ), + ) + .file("duplicate1/src/lib.rs", "") + .file( + "duplicate2/Cargo.toml", + &format!( + r#" + [package] + name = "duplicate" + version = "0.5.0" + edition = "2015" + publish = true + "# + ), + ) + .file("duplicate2/src/lib.rs", "") + }); + + let p = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.duplicate] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() { }") + .build(); + + p.cargo("build").run(); + p.cargo("run") + .with_stderr_data(str![[r#" +[WARNING] skipping duplicate package `duplicate v0.5.0 ([ROOTURL]/dep#[..])`: + [ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate2/Cargo.toml +in favor of [ROOT]/home/.cargo/git/checkouts/dep-[HASH]/[..]/duplicate1/Cargo.toml + +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn unused_ambiguous_published_deps() { + let project = project(); + let git_project = git::new("dep", |project| { + project + .file( + "unique/Cargo.toml", + &format!( + r#" + [package] + name = "unique" + version = "0.5.0" + edition = "2015" + publish = true + "# + ), + ) + .file("unique/src/lib.rs", "") + .file( + "duplicate1/Cargo.toml", + &format!( + r#" + [package] + name = "duplicate" + version = "0.5.0" + edition = "2015" + publish = true + "# + ), + ) + .file("duplicate1/src/lib.rs", "") + .file( + "duplicate2/Cargo.toml", + &format!( + r#" + [package] + name = "duplicate" + version = "0.5.0" + edition = "2015" + publish = true + "# + ), + ) + .file("duplicate2/src/lib.rs", "") + .file( + "invalid/Cargo.toml", + &format!( + r#" + [package + name = "bar" + version = "0.5.0" + edition = "2015" + publish = true + "# + ), + ) + .file("invalid/src/lib.rs", "") + }); + + let p = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.unique] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() { }") + .build(); + + p.cargo("build").run(); + p.cargo("run") + .with_stderr_data(str![[r#" +[ERROR] invalid table header +expected `.`, `]` + --> ../home/.cargo/git/checkouts/dep-[HASH]/[..]/invalid/Cargo.toml:2:29 + | +2 | [package + | ^ + | +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn two_deps_only_update_one() { + let project = project(); + let git1 = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file("src/lib.rs", "") + }); + let git2 = git::new("dep2", |project| { + project + .file("Cargo.toml", &basic_manifest("dep2", "0.5.0")) + .file("src/lib.rs", "") + }); + + let p = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + git = '{}' + [dependencies.dep2] + git = '{}' + "#, + git1.url(), + git2.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + fn oid_to_short_sha(oid: git2::Oid) -> String { + oid.to_string()[..8].to_string() + } + fn git_repo_head_sha(p: &Project) -> String { + let repo = git2::Repository::open(p.root()).unwrap(); + let head = repo.head().unwrap().target().unwrap(); + oid_to_short_sha(head) + } + + println!("dep1 head sha: {}", git_repo_head_sha(&git1)); + println!("dep2 head sha: {}", git_repo_head_sha(&git2)); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[UPDATING] git repository `[ROOTURL]/dep2` +[LOCKING] 2 packages to latest compatible versions +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[CHECKING] dep2 v0.5.0 ([ROOTURL]/dep2#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + git1.change_file("src/lib.rs", "pub fn foo() {}"); + let repo = git2::Repository::open(&git1.root()).unwrap(); + git::add(&repo); + let oid = git::commit(&repo); + println!("dep1 head sha: {}", oid_to_short_sha(oid)); + + p.cargo("update dep1") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[UPDATING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) -> #[..] + +"#]]) + .run(); +} + +#[cargo_test] +fn stale_cached_version() { + let bar = git::new("meta-dep", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.0.0")) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + }); + + // Update the git database in the cache with the current state of the git + // repo + let foo = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies.bar] + git = '{}' + "#, + bar.url() + ), + ) + .file( + "src/main.rs", + r#" + extern crate bar; + + fn main() { assert_eq!(bar::bar(), 1) } + "#, + ) + .build(); + + foo.cargo("build").run(); + foo.process(&foo.bin("foo")).run(); + + // Update the repo, and simulate someone else updating the lock file and then + // us pulling it down. + bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 1 + 0 }"); + let repo = git2::Repository::open(&bar.root()).unwrap(); + git::add(&repo); + git::commit(&repo); + + sleep_ms(1000); + + let rev = repo.revparse_single("HEAD").unwrap().id(); + + foo.change_file( + "Cargo.lock", + &format!( + r#" + [[package]] + name = "foo" + version = "0.0.0" + dependencies = [ + 'bar 0.0.0 (git+{url}#{hash})' + ] + + [[package]] + name = "bar" + version = "0.0.0" + source = 'git+{url}#{hash}' + "#, + url = bar.url(), + hash = rev + ), + ); + + // Now build! + foo.cargo("build") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/meta-dep` +[COMPILING] bar v0.0.0 ([ROOTURL]/meta-dep#[..]) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + foo.process(&foo.bin("foo")).run(); +} + +#[cargo_test] +fn dep_with_changed_submodule() { + let project = project(); + let git_project = git::new("dep1", |project| { + project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + }); + + let git_project2 = git::new("dep2", |project| { + project.file("lib.rs", "pub fn dep() -> &'static str { \"project2\" }") + }); + + let git_project3 = git::new("dep3", |project| { + project.file("lib.rs", "pub fn dep() -> &'static str { \"project3\" }") + }); + + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let mut sub = git::add_submodule(&repo, &git_project2.url().to_string(), Path::new("src")); + git::commit(&repo); + + let p = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + [dependencies.dep1] + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + " + extern crate dep1; + pub fn main() { println!(\"{}\", dep1::dep()) } + ", + ) + .build(); + + println!("first run"); + p.cargo("run") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[UPDATING] git submodule `[ROOTURL]/dep2` +[LOCKING] 1 package to latest compatible version +[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +project2 + +"#]]) + .run(); + + git_project.change_file( + ".gitmodules", + &format!( + "[submodule \"src\"]\n\tpath = src\n\turl={}", + git_project3.url() + ), + ); + + // Sync the submodule and reset it to the new remote. + sub.sync().unwrap(); + { + let subrepo = sub.open().unwrap(); + subrepo + .remote_add_fetch("origin", "refs/heads/*:refs/heads/*") + .unwrap(); + subrepo + .remote_set_url("origin", &git_project3.url().to_string()) + .unwrap(); + let mut origin = subrepo.find_remote("origin").unwrap(); + origin.fetch(&Vec::::new(), None, None).unwrap(); + let id = subrepo.refname_to_id("refs/remotes/origin/master").unwrap(); + let obj = subrepo.find_object(id, None).unwrap(); + subrepo.reset(&obj, git2::ResetType::Hard, None).unwrap(); + } + sub.add_to_index(true).unwrap(); + git::add(&repo); + git::commit(&repo); + + sleep_ms(1000); + // Update the dependency and carry on! + println!("update"); + p.cargo("update") + .with_stdout_data(str![]) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[UPDATING] git submodule `[ROOTURL]/dep3` +[LOCKING] 1 package to latest compatible version +[UPDATING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) -> #[..] + +"#]]) + .run(); + + println!("last run"); + p.cargo("run") + .with_stderr_data(str![[r#" +[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +project3 + +"#]]) + .run(); +} + +#[cargo_test] +fn dev_deps_with_testing() { + let p2 = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file( + "src/lib.rs", + r#" + pub fn gimme() -> &'static str { "zoidberg" } + "#, + ) + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dev-dependencies.bar] + version = "0.5.0" + git = '{}' + "#, + p2.url() + ), + ) + .file( + "src/main.rs", + r#" + fn main() {} + + #[cfg(test)] + mod tests { + extern crate bar; + #[test] fn foo() { bar::gimme(); } + } + "#, + ) + .build(); + + // Generate a lock file which did not use `bar` to compile, but had to update + // `bar` to generate the lock file + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Make sure we use the previous resolution of `bar` instead of updating it + // a second time. + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test tests::foo ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn git_build_cmd_freshness() { + let foo = git::new("foo", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + .file(".gitignore", "src/bar.rs") + }); + foo.root().move_into_the_past(); + + sleep_ms(1000); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Smoke test to make sure it doesn't compile again + println!("first pass"); + foo.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Modify an ignored file and make sure we don't rebuild + println!("second pass"); + foo.change_file("src/bar.rs", ""); + foo.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn git_name_not_always_needed() { + let p2 = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file( + "src/lib.rs", + r#" + pub fn gimme() -> &'static str { "zoidberg" } + "#, + ) + }); + + let repo = git2::Repository::open(&p2.root()).unwrap(); + let mut cfg = repo.config().unwrap(); + let _ = cfg.remove("user.name"); + let _ = cfg.remove("user.email"); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dev-dependencies.bar] + git = '{}' + "#, + p2.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // Generate a lock file which did not use `bar` to compile, but had to update + // `bar` to generate the lock file + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn git_repo_changing_no_rebuild() { + let bar = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + }); + + // Lock p1 to the first rev in the git repo + let p1 = project() + .at("p1") + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "p1" + version = "0.5.0" + edition = "2015" + authors = [] + build = 'build.rs' + [dependencies.bar] + git = '{}' + "#, + bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .file("build.rs", "fn main() {}") + .build(); + p1.root().move_into_the_past(); + p1.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[COMPILING] p1 v0.5.0 ([ROOT]/p1) +[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Make a commit to lock p2 to a different rev + bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }"); + let repo = git2::Repository::open(&bar.root()).unwrap(); + git::add(&repo); + git::commit(&repo); + + // Lock p2 to the second rev + let p2 = project() + .at("p2") + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "p2" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.bar] + git = '{}' + "#, + bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + p2.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[CHECKING] p2 v0.5.0 ([ROOT]/p2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // And now for the real test! Make sure that p1 doesn't get rebuilt + // even though the git repo has changed. + p1.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn git_dep_build_cmd() { + let p = git::new("foo", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + + version = "0.5.0" + path = "bar" + + [[bin]] + + name = "foo" + "#, + ) + .file("src/foo.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + + [lib] + name = "bar" + path = "src/bar.rs" + "#, + ) + .file( + "bar/src/bar.rs.in", + r#" + pub fn gimme() -> i32 { 0 } + "#, + ) + .file( + "bar/build.rs", + r#" + use std::fs; + fn main() { + fs::copy("src/bar.rs.in", "src/bar.rs").unwrap(); + } + "#, + ) + }); + + p.root().join("bar").move_into_the_past(); + + p.cargo("build").run(); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +0 + +"#]]) + .run(); + + // Touching bar.rs.in should cause the `build` command to run again. + p.change_file("bar/src/bar.rs.in", "pub fn gimme() -> i32 { 1 }"); + + p.cargo("build").run(); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +1 + +"#]]) + .run(); +} + +#[cargo_test] +fn fetch_downloads() { + let bar = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.bar] + git = '{}' + "#, + bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); + + p.cargo("fetch").with_stderr_data(str![]).run(); +} + +#[cargo_test] +fn fetch_downloads_with_git2_first_then_with_gitoxide_and_vice_versa() { + let bar = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + }); + let feature_configuration = if cargo_uses_gitoxide() { + // When we are always using `gitoxide` by default, create the registry with git2 as well as the download… + "-Zgitoxide=internal-use-git2" + } else { + // …otherwise create the registry and the git download with `gitoxide`. + "-Zgitoxide=fetch" + }; + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.bar] + git = '{url}' + "#, + url = bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("fetch") + .arg(feature_configuration) + .masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); + + Package::new("bar", "1.0.0").publish(); // trigger a crates-index change. + p.cargo("fetch").with_stderr_data(str![]).run(); +} + +#[cargo_test] +fn warnings_in_git_dep() { + let bar = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "fn unused() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.bar] + git = '{}' + "#, + bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.5.0 ([ROOTURL]/bar#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn update_ambiguous() { + let bar1 = git::new("bar1", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + }); + let bar2 = git::new("bar2", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.6.0")) + .file("src/lib.rs", "") + }); + let baz = git::new("baz", |project| { + project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "baz" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + git = '{}' + "#, + bar2.url() + ), + ) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.bar] + git = '{}' + [dependencies.baz] + git = '{}' + "#, + bar1.url(), + baz.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile").run(); + p.cargo("update bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] There are multiple `bar` packages in your project, and the specification `bar` is ambiguous. +Please re-run this command with one of the following specifications: + bar@0.5.0 + bar@0.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_one_dep_in_repo_with_many_deps() { + let bar = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.5.0")) + .file("a/src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.bar] + git = '{}' + [dependencies.a] + git = '{}' + "#, + bar.url(), + bar.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile").run(); + p.cargo("update bar") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 0 packages to latest compatible versions + +"#]]) + .run(); +} + +#[cargo_test] +fn switch_deps_does_not_update_transitive() { + let transitive = git::new("transitive", |project| { + project + .file("Cargo.toml", &basic_manifest("transitive", "0.5.0")) + .file("src/lib.rs", "") + }); + let dep1 = git::new("dep1", |project| { + project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "dep" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.transitive] + git = '{}' + "#, + transitive.url() + ), + ) + .file("src/lib.rs", "") + }); + let dep2 = git::new("dep2", |project| { + project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "dep" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.transitive] + git = '{}' + "#, + transitive.url() + ), + ) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.dep] + git = '{}' + "#, + dep1.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[UPDATING] git repository `[ROOTURL]/transitive` +[LOCKING] 2 packages to latest compatible versions +[CHECKING] transitive v0.5.0 ([ROOTURL]/transitive#[..]) +[CHECKING] dep v0.5.0 ([ROOTURL]/dep1#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Update the dependency to point to the second repository, but this + // shouldn't update the transitive dependency which is the same. + p.change_file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.dep] + git = '{}' + "#, + dep2.url() + ), + ); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep2` +[LOCKING] 1 package to latest compatible version +[ADDING] dep v0.5.0 ([ROOTURL]/dep2#[..]) +[CHECKING] dep v0.5.0 ([ROOTURL]/dep2#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn update_one_source_updates_all_packages_in_that_git_source() { + let dep = git::new("dep", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "dep" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.5.0")) + .file("a/src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.dep] + git = '{}' + "#, + dep.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); + + let repo = git2::Repository::open(&dep.root()).unwrap(); + let rev1 = repo.revparse_single("HEAD").unwrap().id(); + + // Just be sure to change a file + dep.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }"); + git::add(&repo); + git::commit(&repo); + + p.cargo("update dep").run(); + let lockfile = p.read_lockfile(); + assert!( + !lockfile.contains(&rev1.to_string()), + "{} in {}", + rev1, + lockfile + ); +} + +#[cargo_test] +fn switch_sources() { + let a1 = git::new("a1", |project| { + project + .file("Cargo.toml", &basic_manifest("a", "0.5.0")) + .file("src/lib.rs", "") + }); + let a2 = git::new("a2", |project| { + project + .file("Cargo.toml", &basic_manifest("a", "0.5.1")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.b] + path = "b" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "b/Cargo.toml", + &format!( + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.a] + git = '{}' + "#, + a1.url() + ), + ) + .file("b/src/lib.rs", "pub fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/a1` +[LOCKING] 2 packages to latest compatible versions +[CHECKING] a v0.5.0 ([ROOTURL]/a1#[..]) +[CHECKING] b v0.5.0 ([ROOT]/foo/b) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + "b/Cargo.toml", + &format!( + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies.a] + git = '{}' + "#, + a2.url() + ), + ); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/a2` +[LOCKING] 1 package to latest compatible version +[ADDING] a v0.5.1 ([ROOTURL]/a2#[..]) +[CHECKING] a v0.5.1 ([ROOTURL]/a2#[..]) +[CHECKING] b v0.5.0 ([ROOT]/foo/b) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn dont_require_submodules_are_checked_out() { + let p = project().build(); + let git1 = git::new("dep1", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .file("a/foo", "") + }); + let git2 = git::new("dep2", |p| p); + + let repo = git2::Repository::open(&git1.root()).unwrap(); + let url = git2.root().to_url().to_string(); + git::add_submodule(&repo, &url, Path::new("a/submodule")); + git::commit(&repo); + + git2::Repository::init(&p.root()).unwrap(); + let url = git1.root().to_url().to_string(); + let dst = paths::home().join("foo"); + git2::Repository::clone(&url, &dst).unwrap(); + + git1.cargo("check -v").cwd(&dst).run(); +} + +#[cargo_test] +fn doctest_same_name() { + let a2 = git::new("a2", |p| { + p.file("Cargo.toml", &basic_manifest("a", "0.5.0")) + .file("src/lib.rs", "pub fn a2() {}") + }); + + let a1 = git::new("a1", |p| { + p.file( + "Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + a = {{ git = '{}' }} + "#, + a2.url() + ), + ) + .file("src/lib.rs", "extern crate a; pub fn a1() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = {{ git = '{}' }} + "#, + a1.url() + ), + ) + .file( + "src/lib.rs", + r#" + #[macro_use] + extern crate a; + "#, + ) + .build(); + + p.cargo("test -v").run(); +} + +#[cargo_test] +fn lints_are_suppressed() { + let a = git::new("a", |p| { + p.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file( + "src/lib.rs", + " + use std::option; + ", + ) + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = {{ git = '{}' }} + "#, + a.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/a` +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.5.0 ([ROOTURL]/a#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn denied_lints_are_allowed() { + let a = git::new("a", |p| { + p.file("Cargo.toml", &basic_manifest("a", "0.5.0")).file( + "src/lib.rs", + " + #![deny(warnings)] + use std::option; + ", + ) + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = {{ git = '{}' }} + "#, + a.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/a` +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.5.0 ([ROOTURL]/a#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn add_a_git_dep() { + let git = git::new("git", |p| { + p.file("Cargo.toml", &basic_manifest("git", "0.5.0")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = {{ path = 'a' }} + git = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + assert!(paths::home().join(".cargo/git/CACHEDIR.TAG").is_file()); + + p.change_file( + "a/Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + git = {{ git = '{}' }} + "#, + git.url() + ), + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn two_at_rev_instead_of_tag() { + let git = git::new("git", |p| { + p.file("Cargo.toml", &basic_manifest("git1", "0.5.0")) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("git2", "0.5.0")) + .file("a/src/lib.rs", "") + }); + + // Make a tag corresponding to the current HEAD + let repo = git2::Repository::open(&git.root()).unwrap(); + let head = repo.head().unwrap().target().unwrap(); + repo.tag( + "v0.1.0", + &repo.find_object(head, None).unwrap(), + &repo.signature().unwrap(), + "make a new tag", + false, + ) + .unwrap(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + git1 = {{ git = '{0}', rev = 'v0.1.0' }} + git2 = {{ git = '{0}', rev = 'v0.1.0' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + p.cargo("check -v").run(); +} + +#[cargo_test] +fn include_overrides_gitignore() { + // Make sure that `package.include` takes precedence over .gitignore. + let p = git::new("foo", |repo| { + repo.file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + include = ["src/lib.rs", "ignored.txt", "Cargo.toml"] + "#, + ) + .file( + ".gitignore", + r#" + /target + Cargo.lock + ignored.txt + "#, + ) + .file("src/lib.rs", "") + .file("ignored.txt", "") + .file("build.rs", "fn main() {}") + }); + + p.cargo("check").run(); + p.change_file("ignored.txt", "Trigger rebuild."); + p.cargo("check -v") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.5.0 ([ROOT]/foo): the precalculated components changed +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `[ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("package --list --allow-dirty") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +ignored.txt +src/lib.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_git_dependency_manifest() { + let project = project(); + let git_project = git::new("dep1", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + + name = "dep1" + version = "0.5.0" + edition = "2015" + authors = ["carlhuda@example.com"] + categories = ["algorithms"] + categories = ["algorithms"] + + [lib] + + name = "dep1" + "#, + ) + .file( + "src/dep1.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + }); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.dep1] + + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + &main_file(r#""{}", dep1::hello()"#, &["dep1"]), + ) + .build(); + + project + .cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[ERROR] duplicate key `categories` in table `package` + --> ../home/.cargo/git/checkouts/dep1-[HASH]/[..]/Cargo.toml:9:21 + | +9 | categories = ["algorithms"] + | ^ + | +[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `dep1` + +Caused by: + Unable to update [ROOTURL]/dep1 + +"#]]) + .run(); +} + +#[cargo_test] +fn failed_submodule_checkout() { + let project = project(); + let git_project = git::new("dep1", |project| { + project.file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + }); + + let git_project2 = git::new("dep2", |project| project.file("lib.rs", "")); + + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = listener.local_addr().unwrap(); + let done = Arc::new(AtomicBool::new(false)); + let done2 = done.clone(); + + let t = thread::spawn(move || { + while !done2.load(Ordering::SeqCst) { + if let Ok((mut socket, _)) = listener.accept() { + drop(socket.write_all(b"foo\r\n")); + } + } + }); + + let repo = git2::Repository::open(&git_project2.root()).unwrap(); + let url = format!("https://{}:{}/", addr.ip(), addr.port()); + { + let mut s = repo.submodule(&url, Path::new("bar"), false).unwrap(); + let subrepo = s.open().unwrap(); + let mut cfg = subrepo.config().unwrap(); + cfg.set_str("user.email", "foo@bar.com").unwrap(); + cfg.set_str("user.name", "Foo Bar").unwrap(); + git::commit(&subrepo); + s.add_finalize().unwrap(); + } + git::commit(&repo); + drop((repo, url)); + + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let url = git_project2.root().to_url().to_string(); + git::add_submodule(&repo, &url, Path::new("src")); + git::commit(&repo); + drop(repo); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + project + .cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... + failed to update submodule `src` +... + failed to update submodule `bar` +... +"#]]) + .run(); + project + .cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... + failed to update submodule `src` +... + failed to update submodule `bar` +... +"#]]) + .run(); + + done.store(true, Ordering::SeqCst); + drop(TcpStream::connect(&addr)); + t.join().unwrap(); +} + +#[cargo_test(requires = "git")] +fn use_the_cli() { + let project = project(); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file("src/lib.rs", "") + }); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + " + [net] + git-fetch-with-cli = true + ", + ) + .build(); + + let stderr = str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[RUNNING] `git fetch --no-tags --verbose --force --update-head-ok [..][ROOTURL]/dep1[..] [..]+HEAD:refs/remotes/origin/HEAD[..]` +From [ROOTURL]/dep1 + * [new ref] [..] -> origin/HEAD[..] +[LOCKING] 1 package to latest compatible version +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[RUNNING] `rustc --crate-name dep1 [..]` +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]; + + project + .cargo("check -v") + .env("LC_ALL", "C") + .with_stderr_data(stderr) + .run(); + assert!(paths::home().join(".cargo/git/CACHEDIR.TAG").is_file()); +} + +#[cargo_test] +fn templatedir_doesnt_cause_problems() { + let git_project2 = git::new("dep2", |project| { + project + .file("Cargo.toml", &basic_manifest("dep2", "0.5.0")) + .file("src/lib.rs", "") + }); + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "fo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + fs::write( + paths::home().join(".gitconfig"), + format!( + r#" + [init] + templatedir = {} + "#, + git_project2 + .url() + .to_file_path() + .unwrap() + .to_str() + .unwrap() + .replace("\\", "/") + ), + ) + .unwrap(); + + p.cargo("check").run(); +} + +#[cargo_test(requires = "git")] +fn git_with_cli_force() { + // Supports a force-pushed repo. + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", r#"pub fn f() { println!("one"); }"#) + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2018" + + [dependencies] + dep1 = {{ git = "{}" }} + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() { dep1::f(); }") + .file( + ".cargo/config.toml", + " + [net] + git-fetch-with-cli = true + ", + ) + .build(); + p.cargo("build").run(); + p.rename_run("foo", "foo1") + .with_stdout_data(str![[r#" +one + +"#]]) + .run(); + + // commit --amend a change that will require a force fetch. + let repo = git2::Repository::open(&git_project.root()).unwrap(); + git_project.change_file("src/lib.rs", r#"pub fn f() { println!("two"); }"#); + git::add(&repo); + let id = repo.refname_to_id("HEAD").unwrap(); + let commit = repo.find_commit(id).unwrap(); + let tree_id = t!(t!(repo.index()).write_tree()); + t!(commit.amend( + Some("HEAD"), + None, + None, + None, + None, + Some(&t!(repo.find_tree(tree_id))) + )); + // Perform the fetch. + p.cargo("update").run(); + p.cargo("build").run(); + p.rename_run("foo", "foo2") + .with_stdout_data(str![[r#" +two + +"#]]) + .run(); +} + +#[cargo_test(requires = "git")] +fn git_fetch_cli_env_clean() { + // This tests that git-fetch-with-cli works when GIT_DIR environment + // variable is set (for whatever reason). + let git_dep = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file("src/lib.rs", "") + }); + + let git_proj = git::new("foo", |project| { + project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + dep1 = {{ git = '{}' }} + "#, + git_dep.url() + ), + ) + .file("src/lib.rs", "pub extern crate dep1;") + .file( + ".cargo/config.toml", + " + [net] + git-fetch-with-cli = true + ", + ) + }); + + // The directory set here isn't too important. Pointing to our own git + // directory causes git to be confused and fail. Can also point to an + // empty directory, or a nonexistent one. + git_proj + .cargo("fetch") + .env("GIT_DIR", git_proj.root().join(".git")) + .run(); +} + +#[cargo_test] +fn dirty_submodule() { + // `cargo package` warns for dirty file in submodule. + let (git_project, repo) = git::new_repo("foo", |project| { + project + .file("Cargo.toml", &basic_manifest("foo", "0.5.0")) + // This is necessary because `git::add` is too eager. + .file(".gitignore", "/target") + }); + let git_project2 = git::new("src", |project| { + project.no_manifest().file("lib.rs", "pub fn f() {}") + }); + + let url = git_project2.root().to_url().to_string(); + git::add_submodule(&repo, &url, Path::new("src")); + + // Submodule added, but not committed. + git_project + .cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +.gitmodules + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + + git::commit(&repo); + git_project.cargo("package --no-verify").run(); + + // Modify file, check for warning. + git_project.change_file("src/lib.rs", ""); + git_project + .cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +src/lib.rs + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + // Commit the change. + let sub_repo = git2::Repository::open(git_project.root().join("src")).unwrap(); + git::add(&sub_repo); + git::commit(&sub_repo); + git::add(&repo); + git::commit(&repo); + git_project.cargo("package --no-verify").run(); + + // Try with a nested submodule. + let git_project3 = git::new("bar", |project| project.no_manifest().file("mod.rs", "")); + let url = git_project3.root().to_url().to_string(); + git::add_submodule(&sub_repo, &url, Path::new("bar")); + git_project + .cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +src/.gitmodules + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + + // Commit the submodule addition. + git::commit(&sub_repo); + git::add(&repo); + git::commit(&repo); + git_project.cargo("package --no-verify").run(); + // Modify within nested submodule. + git_project.change_file("src/bar/new_file.rs", "//test"); + git_project + .cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +src/bar/new_file.rs + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + // And commit the change. + let sub_sub_repo = git2::Repository::open(git_project.root().join("src/bar")).unwrap(); + git::add(&sub_sub_repo); + git::commit(&sub_sub_repo); + git::add(&sub_repo); + git::commit(&sub_repo); + git::add(&repo); + git::commit(&repo); + git_project.cargo("package --no-verify").run(); +} + +#[cargo_test] +fn default_not_master() { + let project = project(); + + // Create a repository with a `master` branch, but switch the head to a + // branch called `main` at the same time. + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "pub fn foo() {}") + }); + let head_id = repo.head().unwrap().target().unwrap(); + let head = repo.find_commit(head_id).unwrap(); + repo.branch("main", &head, false).unwrap(); + repo.set_head("refs/heads/main").unwrap(); + + // Then create a commit on the new `main` branch so `master` and `main` + // differ. + git_project.change_file("src/lib.rs", "pub fn bar() {}"); + git::add(&repo); + git::commit(&repo); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + [dependencies] + dep1 = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "pub fn foo() { dep1::bar() }") + .build(); + + project + .cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn historical_lockfile_works() { + let project = project(); + + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + let head_id = repo.head().unwrap().target().unwrap(); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies] + dep1 = {{ git = '{}', branch = 'master' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + project.cargo("check").run(); + project.change_file( + "Cargo.lock", + &format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "dep1" +version = "0.5.0" +source = "git+{}#{}" + +[[package]] +name = "foo" +version = "0.5.0" +dependencies = [ + "dep1", +] +"#, + git_project.url(), + head_id + ), + ); + project + .cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ADDING] dep1 v0.5.0 ([ROOTURL]/dep1?branch=master#[..]) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn historical_lockfile_works_with_vendor() { + let project = project(); + + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + let head_id = repo.head().unwrap().target().unwrap(); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies] + dep1 = {{ git = '{}', branch = 'master' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + let output = project.cargo("vendor").run(); + project.change_file( + ".cargo/config.toml", + str::from_utf8(&output.stdout).unwrap(), + ); + project.change_file( + "Cargo.lock", + &format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "dep1" +version = "0.5.0" +source = "git+{}#{}" + +[[package]] +name = "foo" +version = "0.5.0" +dependencies = [ + "dep1", +] +"#, + git_project.url(), + head_id + ), + ); + project.cargo("check").run(); +} + +#[cargo_test] +fn two_dep_forms() { + let project = project(); + + let (git_project, _repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + + let project = project + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + [dependencies] + dep1 = {{ git = '{}', branch = 'master' }} + a = {{ path = 'a' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + [dependencies] + dep1 = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("a/src/lib.rs", "") + .build(); + + // This'll download the git repository twice, one with HEAD and once with + // the master branch. Then it'll compile 4 crates, the 2 git deps, then + // the two local deps. + project + .cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/dep1` +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 3 packages to latest compatible versions +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1?branch=master#[..]) +[CHECKING] a v0.5.0 ([ROOT]/foo/a) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn metadata_master_consistency() { + // SourceId consistency in the `cargo metadata` output when `master` is + // explicit or implicit, using new or old Cargo.lock. + let (git_project, git_repo) = git::new_repo("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + let bar_hash = git_repo.head().unwrap().target().unwrap().to_string(); + + // Explicit branch="master" with a lock file created before 1.47 (does not contain ?branch=master). + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = "{}", branch = "master" }} + "#, + git_project.url() + ), + ) + .file( + "Cargo.lock", + &format!( + r#" + [[package]] + name = "bar" + version = "1.0.0" + source = "git+{}#{}" + + [[package]] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar", + ] + "#, + git_project.url(), + bar_hash, + ), + ) + .file("src/lib.rs", "") + .build(); + + let metadata = |bar_source| -> String { + r#" + { + "packages": [ + { + "name": "bar", + "version": "1.0.0", + "id": "__BAR_SOURCE__#1.0.0", + "license": null, + "license_file": null, + "description": null, + "source": "__BAR_SOURCE__#__BAR_HASH__", + "dependencies": [], + "targets": "{...}", + "features": {}, + "manifest_path": "[..]", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "default_run": null, + "keywords": [], + "readme": null, + "repository": null, + "rust_version": null, + "homepage": null, + "documentation": null, + "edition": "2015", + "links": null + }, + { + "name": "foo", + "version": "0.1.0", + "id": "[..]foo#0.1.0", + "license": null, + "license_file": null, + "description": null, + "source": null, + "dependencies": [ + { + "name": "bar", + "source": "__BAR_SOURCE__", + "req": "*", + "kind": null, + "rename": null, + "optional": false, + "uses_default_features": true, + "features": [], + "target": null, + "registry": null + } + ], + "targets": "{...}", + "features": {}, + "manifest_path": "[..]", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "default_run": null, + "keywords": [], + "readme": null, + "repository": null, + "rust_version": null, + "homepage": null, + "documentation": null, + "edition": "2015", + "links": null + } + ], + "workspace_members": [ + "[..]foo#0.1.0" + ], + "workspace_default_members": [ + "[..]foo#0.1.0" + ], + "resolve": { + "nodes": [ + { + "id": "__BAR_SOURCE__#1.0.0", + "dependencies": [], + "deps": [], + "features": [] + }, + { + "id": "[..]foo#0.1.0", + "dependencies": [ + "__BAR_SOURCE__#1.0.0" + ], + "deps": [ + { + "name": "bar", + "pkg": "__BAR_SOURCE__#1.0.0", + "dep_kinds": [ + { + "kind": null, + "target": null + } + ] + } + ], + "features": [] + } + ], + "root": "[..]foo#0.1.0" + }, + "target_directory": "[..]", + "version": 1, + "workspace_root": "[..]", + "metadata": null + } + "# + .replace("__BAR_SOURCE__", bar_source) + .replace("__BAR_HASH__", &bar_hash) + }; + + let bar_source = "git+[ROOTURL]/bar?branch=master"; + p.cargo("metadata") + .with_stdout_data(&metadata(&bar_source).is_json()) + .run(); + + // Conversely, remove branch="master" from Cargo.toml, but use a new Cargo.lock that has ?branch=master. + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = "{}" }} + "#, + git_project.url() + ), + ) + .file( + "Cargo.lock", + &format!( + r#" + [[package]] + name = "bar" + version = "1.0.0" + source = "git+{}?branch=master#{}" + + [[package]] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar", + ] + "#, + git_project.url(), + bar_hash + ), + ) + .file("src/lib.rs", "") + .build(); + + // No ?branch=master! + let bar_source = "git+[ROOTURL]/bar"; + p.cargo("metadata") + .with_stdout_data(&metadata(&bar_source).is_json()) + .run(); +} + +#[cargo_test] +fn git_with_force_push() { + // Checks that cargo can handle force-pushes to git repos. + // This works by having a git dependency that is updated with an amend + // commit, and tries with various forms (default branch, branch, rev, + // tag). + let main = |text| format!(r#"pub fn f() {{ println!("{}"); }}"#, text); + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", &main("one")) + }); + let manifest = |extra| { + format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2018" + + [dependencies] + dep1 = {{ git = "{}"{} }} + "#, + git_project.url(), + extra + ) + }; + let p = project() + .file("Cargo.toml", &manifest("")) + .file("src/main.rs", "fn main() { dep1::f(); }") + .build(); + // Download the original and make sure it is OK. + p.cargo("build").run(); + p.rename_run("foo", "foo1") + .with_stdout_data(str![[r#" +one + +"#]]) + .run(); + + let find_head = || t!(t!(repo.head()).peel_to_commit()); + + let amend_commit = |text| { + // commit --amend a change that will require a force fetch. + git_project.change_file("src/lib.rs", &main(text)); + git::add(&repo); + let commit = find_head(); + let tree_id = t!(t!(repo.index()).write_tree()); + t!(commit.amend( + Some("HEAD"), + None, + None, + None, + None, + Some(&t!(repo.find_tree(tree_id))) + )); + }; + + let mut rename_annoyance = 1; + + let mut verify = |text| { + // Perform the fetch. + p.cargo("update").run(); + p.cargo("build").run(); + rename_annoyance += 1; + p.rename_run("foo", &format!("foo{}", rename_annoyance)) + .with_stdout_data(text) + .run(); + }; + + amend_commit("two"); + verify(str![[r#" +two + +"#]]); + + // Try with a rev. + let head1 = find_head().id().to_string(); + let extra = format!(", rev = \"{}\"", head1); + p.change_file("Cargo.toml", &manifest(&extra)); + verify(str![[r#" +two + +"#]]); + amend_commit("three"); + let head2 = find_head().id().to_string(); + assert_ne!(&head1, &head2); + let extra = format!(", rev = \"{}\"", head2); + p.change_file("Cargo.toml", &manifest(&extra)); + verify(str![[r#" +three + +"#]]); + + // Try with a tag. + git::tag(&repo, "my-tag"); + p.change_file("Cargo.toml", &manifest(", tag = \"my-tag\"")); + verify(str![[r#" +three + +"#]]); + amend_commit("tag-three"); + let head = t!(t!(repo.head()).peel(git2::ObjectType::Commit)); + t!(repo.tag("my-tag", &head, &t!(repo.signature()), "move tag", true)); + verify(str![[r#" +tag-three + +"#]]); + + // Try with a branch. + let br = t!(repo.branch("awesome-stuff", &find_head(), false)); + t!(repo.checkout_tree(&t!(br.get().peel(git2::ObjectType::Tree)), None)); + t!(repo.set_head("refs/heads/awesome-stuff")); + git_project.change_file("src/lib.rs", &main("awesome-three")); + git::add(&repo); + git::commit(&repo); + p.change_file("Cargo.toml", &manifest(", branch = \"awesome-stuff\"")); + verify(str![[r#" +awesome-three + +"#]]); + amend_commit("awesome-four"); + verify(str![[r#" +awesome-four + +"#]]); +} + +#[cargo_test] +fn corrupted_checkout() { + // Test what happens if the checkout is corrupted somehow. + _corrupted_checkout(false); +} + +#[cargo_test] +fn corrupted_checkout_with_cli() { + // Test what happens if the checkout is corrupted somehow with git cli. + _corrupted_checkout(true); +} + +fn _corrupted_checkout(with_cli: bool) { + let (git_project, repository) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file("src/lib.rs", "") + }); + + let project2 = git::new("dep2", |project| { + project.no_manifest().file("README.md", "") + }); + let url = project2.root().to_url().to_string(); + add_submodule(&repository, &url, Path::new("dep2")); + git::commit(&repository); + drop(repository); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep1 = {{ git = "{}" }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch").run(); + + let mut dep1_co_paths = t!(glob::glob( + paths::home() + .join(".cargo/git/checkouts/dep1-*/*") + .to_str() + .unwrap() + )); + let dep1_co_path = dep1_co_paths.next().unwrap().unwrap(); + let dep1_ok = dep1_co_path.join(".cargo-ok"); + let dep1_manifest = dep1_co_path.join("Cargo.toml"); + let dep2_readme = dep1_co_path.join("dep2/README.md"); + + // Deleting this file simulates an interrupted checkout. + t!(fs::remove_file(&dep1_ok)); + t!(fs::remove_file(&dep1_manifest)); + t!(fs::remove_file(&dep2_readme)); + + // This should refresh the checkout. + let mut e = p.cargo("fetch"); + if with_cli { + e.env("CARGO_NET_GIT_FETCH_WITH_CLI", "true"); + } + e.run(); + assert!(dep1_ok.exists()); + assert!(dep1_manifest.exists()); + assert!(dep2_readme.exists()); +} + +#[cargo_test] +fn cleans_temp_pack_files() { + // Checks that cargo removes temp files left by libgit2 when it is + // interrupted (see clean_repo_temp_files). + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch").run(); + // Simulate what happens when libgit2 is interrupted while indexing a pack file. + let tmp_path = super::git_gc::find_index().join(".git/objects/pack/pack_git2_91ab40da04fdc2e7"); + fs::write(&tmp_path, "test").unwrap(); + let mut perms = fs::metadata(&tmp_path).unwrap().permissions(); + perms.set_readonly(true); + fs::set_permissions(&tmp_path, perms).unwrap(); + + // Trigger an index update. + p.cargo("generate-lockfile").run(); + assert!(!tmp_path.exists()); +} + +#[cargo_test] +fn different_user_relative_submodules() { + let user1_git_project = git::new("user1/dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + + let user2_git_project = git::new("user2/dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + let _user2_git_project2 = git::new("user2/dep2", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + + let user2_repo = git2::Repository::open(&user2_git_project.root()).unwrap(); + let url = "../dep2"; + git::add_submodule(&user2_repo, url, Path::new("dep2")); + git::commit(&user2_repo); + + let user1_repo = git2::Repository::open(&user1_git_project.root()).unwrap(); + let url = user2_git_project.url(); + git::add_submodule(&user1_repo, url.as_str(), Path::new("user2/dep1")); + git::commit(&user1_repo); + + let project = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep1] + git = '{}' + "#, + user1_git_project.url() + ), + ) + .file("src/main.rs", &main_file(r#""hello""#, &[])) + .build(); + + project + .cargo("build") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/user1/dep1` +[UPDATING] git submodule `[ROOTURL]/user2/dep1` +[UPDATING] git submodule `[ROOTURL]/user2/dep2` +[LOCKING] 1 package to latest compatible version +[COMPILING] dep1 v0.5.0 ([ROOTURL]/user1/dep1#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(project.bin("foo").is_file()); +} + +#[cargo_test] +fn git_worktree_with_original_repo_renamed() { + let project = project().build(); + let git_project = git::new("foo", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + license = "MIR OR Apache-2.0" + description = "A test!" + homepage = "https://example.org" + documentation = "" + repository = "https://example.org" + readme = "./README.md" + "#, + ) + .file("src/lib.rs", "") + .file("README.md", "") + }); + + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let repo_root = repo.workdir().unwrap().parent().unwrap(); + let opts = git2::WorktreeAddOptions::new(); + let _ = repo + .worktree("bar", &repo_root.join("bar"), Some(&opts)) + .unwrap(); + + // Rename the original repository + let new = repo_root.join("foo2"); + fs::rename(&git_project.root(), &new).unwrap(); + + project + .cargo("package --list") + .cwd(&new) + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +README.md +src/lib.rs + +"#]]) + .run(); + + project + .cargo("check") + .cwd(&new) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/foo2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(public_network_test, requires = "git")] +fn github_fastpath_error_message() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bitflags = { git = "https://github.com/rust-lang/bitflags.git", rev="11111b376b93484341c68fbca3ca110ae5cd2790" } + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .env("CARGO_NET_GIT_FETCH_WITH_CLI", "true") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `https://github.com/rust-lang/bitflags.git` +fatal: remote [ERROR] upload-pack: not our ref 11111b376b93484341c68fbca3ca110ae5cd2790 +[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bitflags` + +Caused by: + Unable to update https://github.com/rust-lang/bitflags.git?rev=11111b376b93484341c68fbca3ca110ae5cd2790 + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH] + +Caused by: + revision 11111b376b93484341c68fbca3ca110ae5cd2790 not found + +Caused by: + process didn't exit successfully: `git fetch --no-tags --force --update-head-ok [..] + +"#]]) + .run(); +} + +#[cargo_test(public_network_test)] +fn git_fetch_libgit2_error_message() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bitflags = { git = "https://github.com/rust-lang/bitflags.git", rev="11111b376b93484341c68fbca3ca110ae5cd2790" } + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `https://github.com/rust-lang/bitflags.git` +... +[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bitflags` + +Caused by: + Unable to update https://github.com/rust-lang/bitflags.git?rev=11111b376b93484341c68fbca3ca110ae5cd2790 + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH] + +Caused by: + revision 11111b376b93484341c68fbca3ca110ae5cd2790 not found +... +"#]]) + .run(); +} + +#[cargo_test] +fn git_worktree_with_bare_original_repo() { + let project = project().build(); + let git_project = git::new("foo", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + license = "MIR OR Apache-2.0" + description = "A test!" + homepage = "https://example.org" + documentation = "" + repository = "https://example.org" + readme = "./README.md" + "#, + ) + .file("src/lib.rs", "") + .file("README.md", "") + }); + + // Create a "bare" Git repository. + // Keep the `.git` folder and delete the others. + let repo = { + let mut repo_builder = git2::build::RepoBuilder::new(); + repo_builder + .bare(true) + .clone_local(git2::build::CloneLocal::Local) + .clone( + git_project.root().to_url().as_str(), + &paths::root().join("foo-bare"), + ) + .unwrap() + }; + assert!(repo.is_bare()); + let opts = git2::WorktreeAddOptions::new(); + let wt = repo + .worktree("bar", &paths::root().join("bar"), Some(&opts)) + .unwrap(); + + project + .cargo("package --list") + .cwd(wt.path()) + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +README.md +src/lib.rs + +"#]]) + .run(); + + project + .cargo("check") + .cwd(wt.path()) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(unix)] +fn simple_with_fifo() { + let git_project = git::new("foo", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + }); + + std::process::Command::new("mkfifo") + .current_dir(git_project.root()) + .arg(git_project.root().join("blocks-when-read")) + .status() + .expect("a FIFO can be created"); + + // Avoid actual blocking even in case of failure, assuming that what it lists here + // would also be read eventually. + git_project + .cargo("package -l") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_auth.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_auth.rs new file mode 100644 index 000000000..c5fb5532a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_auth.rs @@ -0,0 +1,480 @@ +//! Tests for git authentication. + +use std::collections::HashSet; +use std::io::prelude::*; +use std::io::BufReader; +use std::net::{SocketAddr, TcpListener}; +use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +use std::sync::Arc; +use std::thread::{self, JoinHandle}; + +use cargo_test_support::basic_manifest; +use cargo_test_support::git::cargo_uses_gitoxide; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::project; + +fn setup_failed_auth_test() -> (SocketAddr, JoinHandle<()>, Arc) { + let server = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = server.local_addr().unwrap(); + + fn headers(rdr: &mut dyn BufRead) -> HashSet { + let valid = ["GET", "Authorization", "Accept"]; + rdr.lines() + .map(|s| s.unwrap()) + .take_while(|s| s.len() > 2) + .map(|s| s.trim().to_string()) + .filter(|s| valid.iter().any(|prefix| s.starts_with(*prefix))) + .collect() + } + + let connections = Arc::new(AtomicUsize::new(0)); + let connections2 = connections.clone(); + let t = thread::spawn(move || { + let mut conn = BufReader::new(server.accept().unwrap().0); + let req = headers(&mut conn); + connections2.fetch_add(1, SeqCst); + conn.get_mut() + .write_all( + b"HTTP/1.1 401 Unauthorized\r\n\ + WWW-Authenticate: Basic realm=\"wheee\"\r\n\ + Content-Length: 0\r\n\ + \r\n", + ) + .unwrap(); + assert_eq!( + req, + vec![ + "GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1", + "Accept: */*", + ] + .into_iter() + .map(|s| s.to_string()) + .collect() + ); + + let req = headers(&mut conn); + connections2.fetch_add(1, SeqCst); + conn.get_mut() + .write_all( + b"HTTP/1.1 401 Unauthorized\r\n\ + WWW-Authenticate: Basic realm=\"wheee\"\r\n\ + \r\n", + ) + .unwrap(); + assert_eq!( + req, + vec![ + "GET /foo/bar/info/refs?service=git-upload-pack HTTP/1.1", + "Authorization: Basic Zm9vOmJhcg==", + "Accept: */*", + ] + .into_iter() + .map(|s| s.to_string()) + .collect() + ); + }); + + let script = project() + .at("script") + .file("Cargo.toml", &basic_manifest("script", "0.1.0")) + .file( + "src/main.rs", + r#" + fn main() { + println!("username=foo"); + println!("password=bar"); + } + "#, + ) + .build(); + + script.cargo("build -v").run(); + let script = script.bin("script"); + + let config = paths::home().join(".gitconfig"); + let mut config = git2::Config::open(&config).unwrap(); + config + .set_str( + "credential.helper", + // This is a bash script so replace `\` with `/` for Windows + &script.display().to_string().replace("\\", "/"), + ) + .unwrap(); + (addr, t, connections) +} + +// Tests that HTTP auth is offered from `credential.helper`. +#[cargo_test] +fn http_auth_offered() { + let (addr, t, connections) = setup_failed_auth_test(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "http://127.0.0.1:{}/foo/bar" + "#, + addr.port() + ), + ) + .file("src/main.rs", "") + .file( + ".cargo/config.toml", + "[net] + retry = 0 + ", + ) + .build(); + + // This is a "contains" check because the last error differs by platform, + // may span multiple lines, and isn't relevant to this test. + p.cargo("check") + .with_status(101) + .with_stderr_data(&format!( + "\ +[UPDATING] git repository `http://{addr}/foo/bar` +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update http://{addr}/foo/bar + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: + failed to authenticate when downloading repository + + * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect + + if the git CLI succeeds then `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: +{trailer} +", + trailer = if cargo_uses_gitoxide() { + format!(r#"[CREDENTIAL]s provided for "http://{addr}/foo/bar" were not accepted by the remote + +Caused by: + Received HTTP status 401"#) + } else { + " no authentication methods succeeded".to_string() + } + )) + .run(); + assert_eq!(connections.load(SeqCst), 2); + t.join().ok().unwrap(); +} + +// Boy, sure would be nice to have a TLS implementation in rust! +#[cargo_test] +fn https_something_happens() { + let server = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = server.local_addr().unwrap(); + let t = thread::spawn(move || { + let mut conn = server.accept().unwrap().0; + drop(conn.write(b"1234")); + drop(conn.shutdown(std::net::Shutdown::Write)); + drop(conn.read(&mut [0; 16])); + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "https://127.0.0.1:{}/foo/bar" + "#, + addr.port() + ), + ) + .file("src/main.rs", "") + .file( + ".cargo/config.toml", + "[net] + retry = 0 + ", + ) + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(&format!( + "\ +[UPDATING] git repository `https://{addr}/foo/bar` +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update https://{addr}/foo/bar + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: +{errmsg} +", + errmsg = if cargo_uses_gitoxide() { + r" network failure seems to have happened + if a proxy or similar is necessary `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: + An IO error occurred when talking to the server + +Caused by: + [35] SSL connect error ([..])" + } else if cfg!(windows) { + "[..]failed to send request: [..]\n..." + } else if cfg!(target_os = "macos") { + // macOS is difficult to tests as some builds may use Security.framework, + // while others may use OpenSSL. In that case, let's just not verify the error + // message here. + "..." + } else { + "[..]SSL [ERROR][..]" + } + )) + .run(); + + t.join().ok().unwrap(); +} + +// It would sure be nice to have an SSH implementation in Rust! +#[cargo_test] +fn ssh_something_happens() { + let server = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = server.local_addr().unwrap(); + let t = thread::spawn(move || { + drop(server.accept().unwrap()); + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "ssh://127.0.0.1:{}/foo/bar" + "#, + addr.port() + ), + ) + .file("src/main.rs", "") + .build(); + + let expected = if cargo_uses_gitoxide() { + // Due to the usage of `ssh` and `ssh.exe` respectively, the messages change. + // This will be adjusted to use `ssh2` to get rid of this dependency and have uniform messaging. + let message = if cfg!(windows) { + // The order of multiple possible messages isn't deterministic within `ssh`, and `gitoxide` detects both + // but gets to report only the first. Thus this test can flip-flop from one version of the error to the other + // and we can't test for that. + // We'd want to test for: + // "[..]ssh: connect to host 127.0.0.1 [..]" + // ssh: connect to host example.org port 22: No route to host + // "[..]banner exchange: Connection to 127.0.0.1 [..]" + // banner exchange: Connection to 127.0.0.1 port 62250: Software caused connection abort + // But since there is no common meaningful sequence or word, we can only match a small telling sequence of characters. + "[..]onnect[..]" + } else { + "[..]Connection [..] by [..]" + }; + format!( + "\ +[UPDATING] git repository `ssh://{addr}/foo/bar` +... +{message} +... +" + ) + } else { + format!( + "\ +[UPDATING] git repository `ssh://{addr}/foo/bar` +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update ssh://{addr}/foo/bar + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: + network failure seems to have happened + if a proxy or similar is necessary `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: + failed to start SSH session: Failed getting banner; class=Ssh (23) +" + ) + }; + p.cargo("check -v") + .with_status(101) + .with_stderr_data(expected) + .run(); + t.join().ok().unwrap(); +} + +#[cargo_test] +fn net_err_suggests_fetch_with_cli() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { git = "ssh://needs-proxy.invalid/git" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(format!( + "\ +[UPDATING] git repository `ssh://needs-proxy.invalid/git` +[WARNING] spurious network error (3 tries remaining): [..] resolve [..] needs-proxy.invalid: [..] known[..] +[WARNING] spurious network error (2 tries remaining): [..] resolve [..] needs-proxy.invalid: [..] known[..] +[WARNING] spurious network error (1 tries remaining): [..] resolve [..] needs-proxy.invalid: [..] known[..] +[ERROR] failed to get `foo` as a dependency of package `foo v0.0.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `foo` + +Caused by: + Unable to update ssh://needs-proxy.invalid/git + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/git-[HASH] + +Caused by: + network failure seems to have happened + if a proxy or similar is necessary `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: +{trailer} +", + trailer = if cargo_uses_gitoxide() { + r" An IO error occurred when talking to the server + +Caused by: + ssh: Could not resolve hostname needs-proxy.invalid[..]" + } else { + " failed to resolve address for needs-proxy.invalid: [..] known[..]; class=Net (12)" + } + )) + .run(); + + p.change_file( + ".cargo/config.toml", + " + [net] + git-fetch-with-cli = true + ", + ); + + p.cargo("check -v") + .with_status(101) + .with_stderr_contains("[..]Unable to update[..]") + .with_stderr_does_not_contain("[..]try enabling `git-fetch-with-cli`[..]") + .run(); +} + +#[cargo_test] +fn instead_of_url_printed() { + let (addr, t, _connections) = setup_failed_auth_test(); + let config = paths::home().join(".gitconfig"); + let mut config = git2::Config::open(&config).unwrap(); + config + .set_str( + &format!("url.http://{}/.insteadOf", addr), + "https://foo.bar/", + ) + .unwrap(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + git = "https://foo.bar/foo/bar" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(&format!( + "\ +[UPDATING] git repository `https://foo.bar/foo/bar` +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update https://foo.bar/foo/bar + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: + failed to authenticate when downloading repository: http://{addr}/foo/bar + + * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect + + if the git CLI succeeds then `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: +... +" + )) + .run(); + + t.join().ok().unwrap(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_gc.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_gc.rs new file mode 100644 index 000000000..5b2cce78f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_gc.rs @@ -0,0 +1,117 @@ +//! Tests for git garbage collection. + +use std::env; +use std::ffi::OsStr; +use std::path::PathBuf; + +use cargo_test_support::git; +use cargo_test_support::git::cargo_uses_gitoxide; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use url::Url; + +pub fn find_index() -> PathBuf { + let dir = paths::home().join(".cargo/registry/index"); + dir.read_dir().unwrap().next().unwrap().unwrap().path() +} + +fn run_test(path_env: Option<&OsStr>) { + const N: usize = 50; + + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + Package::new("bar", "0.1.0").publish(); + + foo.cargo("check").run(); + + let index = find_index(); + let path = paths::home().join("tmp"); + let url = Url::from_file_path(&path).unwrap().to_string(); + let repo = git2::Repository::init(&path).unwrap(); + let index = git2::Repository::open(&index).unwrap(); + let mut cfg = repo.config().unwrap(); + cfg.set_str("user.email", "foo@bar.com").unwrap(); + cfg.set_str("user.name", "Foo Bar").unwrap(); + let mut cfg = index.config().unwrap(); + cfg.set_str("user.email", "foo@bar.com").unwrap(); + cfg.set_str("user.name", "Foo Bar").unwrap(); + + for _ in 0..N { + git::commit(&repo); + index + .remote_anonymous(&url) + .unwrap() + .fetch(&["refs/heads/master:refs/remotes/foo/master"], None, None) + .unwrap(); + } + drop((repo, index)); + Package::new("bar", "0.1.1").publish(); + + let before = find_index() + .join(".git/objects/pack") + .read_dir() + .unwrap() + .count(); + assert!(before > N); + + let mut cmd = foo.cargo("update"); + cmd.env("__CARGO_PACKFILE_LIMIT", "10"); + if let Some(path) = path_env { + cmd.env("PATH", path); + } + cmd.env("CARGO_LOG", "trace"); + cmd.run(); + let after = find_index() + .join(".git/objects/pack") + .read_dir() + .unwrap() + .count(); + assert!( + after < before, + "packfiles before: {}\n\ + packfiles after: {}", + before, + after + ); +} + +#[cargo_test(requires = "git")] +fn use_git_gc() { + run_test(None); +} + +#[cargo_test] +fn avoid_using_git() { + if cargo_uses_gitoxide() { + // file protocol without git binary is currently not possible - needs built-in upload-pack. + // See https://github.com/Byron/gitoxide/issues/734 (support for the file protocol) progress updates. + return; + } + let path = env::var_os("PATH").unwrap_or_default(); + let mut paths = env::split_paths(&path).collect::>(); + let idx = paths + .iter() + .position(|p| p.join("git").exists() || p.join("git.exe").exists()); + match idx { + Some(i) => { + paths.remove(i); + } + None => return, + } + run_test(Some(&env::join_paths(&paths).unwrap())); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_shallow.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_shallow.rs new file mode 100644 index 000000000..86291714c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/git_shallow.rs @@ -0,0 +1,860 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_manifest, git, paths, project}; + +use crate::git_gc::find_index; + +enum Backend { + Git2, + Gitoxide, +} + +impl Backend { + fn to_arg(&self) -> &'static str { + match self { + Backend::Git2 => "", + Backend::Gitoxide => "-Zgitoxide=fetch", + } + } +} + +enum RepoMode { + Shallow, + Complete, +} + +impl RepoMode { + fn to_deps_arg(&self) -> &'static str { + match self { + RepoMode::Complete => "", + RepoMode::Shallow => "-Zgit=shallow-deps", + } + } +} + +#[cargo_test] +fn gitoxide_fetch_shallow_dep_two_revs() { + fetch_dep_two_revs(Backend::Gitoxide, RepoMode::Shallow) +} + +#[cargo_test] +fn git2_fetch_complete_dep_two_revs() { + fetch_dep_two_revs(Backend::Git2, RepoMode::Complete) +} + +fn fetch_dep_two_revs(backend: Backend, mode: RepoMode) { + let bar = git::new("meta-dep", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.0.0")) + .file("src/lib.rs", "pub fn bar() -> i32 { 1 }") + }); + + let repo = git2::Repository::open(&bar.root()).unwrap(); + let rev1 = repo.revparse_single("HEAD").unwrap().id(); + + // Commit the changes and make sure we trigger a recompile + bar.change_file("src/lib.rs", "pub fn bar() -> i32 { 2 }"); + git::add(&repo); + let rev2 = git::commit(&repo); + + let foo = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.0" + authors = [] + + [dependencies.bar] + git = '{}' + rev = "{}" + + [dependencies.baz] + path = "../baz" + "#, + bar.url(), + rev1 + ), + ) + .file( + "src/main.rs", + r#" + extern crate bar; + extern crate baz; + + fn main() { + assert_eq!(bar::bar(), 1); + assert_eq!(baz::baz(), 2); + } + "#, + ) + .build(); + + let _baz = project() + .at("baz") + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "baz" + version = "0.0.0" + authors = [] + + [dependencies.bar] + git = '{}' + rev = "{}" + "#, + bar.url(), + rev2 + ), + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + pub fn baz() -> i32 { bar::bar() } + "#, + ) + .build(); + + foo.cargo("check -v") + .arg_line(backend.to_arg()) + .arg_line(mode.to_deps_arg()) + .env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0") // respect `backend` + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-deps"]) + .run(); +} + +#[cargo_test] +fn gitoxide_fetch_shallow_dep_branch_and_rev() -> anyhow::Result<()> { + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + // this commit would not be available in a shallow fetch. + let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap(); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar-renamed = {{ package = "bar", git = "{}", rev = "{}" }} + bar = {{ git = "{}", branch = "master" }} + "#, + bar.url(), + first_commit_pre_change, + bar.url(), + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-deps") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-deps"]) + .run(); + + let db_paths = glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap())? + .map(Result::unwrap) + .collect::>(); + assert_eq!( + db_paths.len(), + 1, + "only one db checkout source is used per dependency" + ); + let db_clone = gix::open_opts(&db_paths[0], gix::open::Options::isolated())?; + assert!( + db_clone.is_shallow(), + "the repo is shallow while having all data it needs" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_fetch_shallow_dep_branch_to_rev() -> anyhow::Result<()> { + // db exists from previous build, then dependency changes to refer to revision that isn't + // available in the shallow fetch. + + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + // this commit would not be available in a shallow fetch. + let first_commit_pre_change = bar_repo.head().unwrap().target().unwrap(); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ git = "{}", branch = "master" }} + "#, + bar.url(), + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-deps") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-deps"]) + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert!(db_clone.is_shallow()); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ git = "{}", rev = "{}" }} + "#, + bar.url(), + first_commit_pre_change + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-deps") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-deps"]) + .run(); + + assert!( + db_clone.is_shallow(), + "we maintain shallowness and never unshallow" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_fetch_shallow_index_then_git2_fetch_complete() -> anyhow::Result<()> { + 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(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + let shallow_repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + shallow_repo + .rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow fetch always start at depth of 1 to minimize download size" + ); + assert!(shallow_repo.is_shallow()); + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0") + .run(); + + let repo = gix::open_opts( + find_remote_index(RepoMode::Complete), + gix::open::Options::isolated(), + )?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 3, + "an entirely new repo was fetched which is never shallow" + ); + assert!(!repo.is_shallow()); + Ok(()) +} + +#[cargo_test] +fn gitoxide_fetch_shallow_dep_then_git2_fetch_complete() -> anyhow::Result<()> { + // Example where an old lockfile with an explicit branch="master" in Cargo.toml. + Package::new("bar", "1.0.0").publish(); + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 2, + "original repo has initial commit and change commit" + ); + } + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ version = "1.0", git = "{}", branch = "master" }} + "#, + bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-deps") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-deps"]) + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert!(db_clone.is_shallow()); + assert_eq!( + db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 1, + "db fetch are shallow and have a shortened history" + ); + + let dep_checkout = gix::open_opts( + find_lexicographically_first_bar_checkout(), + gix::open::Options::isolated(), + )?; + assert!(dep_checkout.is_shallow()); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "db checkouts are hard-linked fetches with the shallow file copied separately." + ); + + bar.change_file("src/lib.rs", "// another change"); + git::add(&bar_repo); + git::commit(&bar_repo); + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 3, + "original repo has initial commit and change commit, and another change" + ); + } + + p.cargo("update") + .env("__CARGO_USE_GITOXIDE_INSTEAD_OF_GIT2", "0") + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Complete), + gix::open::Options::isolated(), + )?; + assert_eq!( + db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 3, + "the db clone was re-initialized and has all commits" + ); + assert!( + !db_clone.is_shallow(), + "shallow-ness was removed as git2 does not support it" + ); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "the original dep checkout didn't change - there is a new one for each update we get locally" + ); + + let max_history_depth = glob::glob( + paths::home() + .join(".cargo/git/checkouts/bar-*/*/.git") + .to_str() + .unwrap(), + )? + .map(|path| -> anyhow::Result { + let dep_checkout = gix::open_opts(path?, gix::open::Options::isolated())?; + let depth = dep_checkout.head_id()?.ancestors().all()?.count(); + assert_eq!(dep_checkout.is_shallow(), depth == 1, "the first checkout is done with gitoxide and shallow, the second one is git2 non-shallow"); + Ok(depth) + }) + .map(Result::unwrap) + .max() + .expect("two checkout repos"); + + assert_eq!( + max_history_depth, 3, + "the new checkout sees all commits of the non-shallow DB repository" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_fetch_shallow_dep_then_gitoxide_fetch_complete() -> anyhow::Result<()> { + Package::new("bar", "1.0.0").publish(); + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + bar.change_file("src/lib.rs", "// change"); + git::add(&bar_repo); + git::commit(&bar_repo); + + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 2, + "original repo has initial commit and change commit" + ); + } + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ version = "1.0", git = "{}", branch = "master" }} + "#, + bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-deps") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-deps"]) + .run(); + + let shallow_db_clone = gix::open_opts( + find_bar_db(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert!(shallow_db_clone.is_shallow()); + assert_eq!( + shallow_db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 1, + "db fetches are shallow and have a shortened history" + ); + + let dep_checkout = gix::open_opts( + find_lexicographically_first_bar_checkout(), + gix::open::Options::isolated(), + )?; + assert!(dep_checkout.is_shallow()); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "db checkouts are hard-linked fetches with the shallow file copied separately." + ); + + bar.change_file("src/lib.rs", "// another change"); + git::add(&bar_repo); + git::commit(&bar_repo); + { + let mut walk = bar_repo.revwalk()?; + walk.push_head()?; + assert_eq!( + walk.count(), + 3, + "original repo has initial commit and change commit, and another change" + ); + } + + p.cargo("update") + .arg("-Zgitoxide=fetch") // shallow-deps is omitted intentionally + .masquerade_as_nightly_cargo(&["gitoxide=fetch"]) + .run(); + + let db_clone = gix::open_opts( + find_bar_db(RepoMode::Complete), + gix::open::Options::isolated(), + )?; + assert_eq!( + db_clone + .rev_parse_single("origin/master")? + .ancestors() + .all()? + .count(), + 3, + "we created an entirely new non-shallow clone" + ); + assert!(!db_clone.is_shallow()); + assert_eq!( + dep_checkout.head_id()?.ancestors().all()?.count(), + 1, + "the original dep checkout didn't change - there is a new one for each update we get locally" + ); + + let max_history_depth = glob::glob( + paths::home() + .join(".cargo/git/checkouts/bar-*/*/.git") + .to_str() + .unwrap(), + )? + .map(|path| -> anyhow::Result { + let path = path?; + let dep_checkout = gix::open_opts(&path, gix::open::Options::isolated())?; + assert_eq!( + dep_checkout.is_shallow(), + path.to_string_lossy().contains("-shallow"), + "checkouts of shallow db repos are shallow as well" + ); + let depth = dep_checkout.head_id()?.ancestors().all()?.count(); + Ok(depth) + }) + .map(Result::unwrap) + .max() + .expect("two checkout repos"); + + assert_eq!( + max_history_depth, 3, + "we see the previous shallow checkout as well as new unshallow one" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_fetch_shallow_index_then_preserve_shallow() -> anyhow::Result<()> { + 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(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow fetches always start at depth of 1 to minimize download size" + ); + assert!(repo.is_shallow()); + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") // NOTE: the flag needs to be consistent or else a different index is created + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits" + ); + assert!(repo.is_shallow()); + + Package::new("bar", "1.2.0").publish(); + Package::new("bar", "1.3.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow boundaries are moved with each fetch to maintain only a single commit of history" + ); + assert!(repo.is_shallow()); + + Ok(()) +} + +/// If there is shallow *and* non-shallow fetches, non-shallow will naturally be returned due to sort order. +#[cargo_test] +fn gitoxide_fetch_complete_index_then_shallow() -> anyhow::Result<()> { + 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(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch") + .masquerade_as_nightly_cargo(&["gitoxide=fetch"]) + .run(); + + let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 2, + "initial commit and the first crate" + ); + assert!(!repo.is_shallow()); + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + let shallow_repo = gix::open_opts( + find_remote_index(RepoMode::Shallow), + gix::open::Options::isolated(), + )?; + assert_eq!( + shallow_repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "the follow up fetch an entirely new index which is now shallow and which is in its own location" + ); + assert!(shallow_repo.is_shallow()); + + Package::new("bar", "1.2.0").publish(); + Package::new("bar", "1.3.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + assert_eq!( + shallow_repo + .rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "subsequent shallow fetches wont' fetch what's inbetween, only the single commit that we need while leveraging existing commits" + ); + assert!(shallow_repo.is_shallow()); + + p.cargo("update") + .arg("-Zgitoxide=fetch") + .masquerade_as_nightly_cargo(&["gitoxide=fetch"]) + .run(); + + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 5, + "we can separately fetch the non-shallow index as well and it sees all commits" + ); + + Ok(()) +} + +#[cargo_test] +fn gitoxide_fetch_shallow_index_then_abort_and_update() -> anyhow::Result<()> { + 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(); + p.cargo("fetch") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + let repo = gix::open_opts(find_index(), gix::open::Options::isolated())?; + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "shallow fetches always start at depth of 1 to minimize download size" + ); + assert!(repo.is_shallow()); + let shallow_lock = repo.shallow_file().with_extension("lock"); + // adding a lock file and deleting the original simulates a left-over fetch that was aborted, leaving a lock file + // in place without ever having moved it to the right location. + std::fs::write(&shallow_lock, &[])?; + std::fs::remove_file(repo.shallow_file())?; + + Package::new("bar", "1.1.0").publish(); + p.cargo("update") + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-index") + .masquerade_as_nightly_cargo(&["gitoxide=fetch", "git=shallow-index"]) + .run(); + + assert!(!shallow_lock.is_file(), "the repository was re-initialized"); + assert!(repo.is_shallow()); + assert_eq!( + repo.rev_parse_single("origin/HEAD")? + .ancestors() + .all()? + .count(), + 1, + "it's a fresh shallow fetch - otherwise it would have 2 commits if the previous shallow fetch would still be present" + ); + + Ok(()) +} + +fn find_lexicographically_first_bar_checkout() -> std::path::PathBuf { + glob::glob( + paths::home() + .join(".cargo/git/checkouts/bar-*/*/.git") + .to_str() + .unwrap(), + ) + .unwrap() + .next() + .unwrap() + .unwrap() + .to_owned() +} + +fn find_remote_index(mode: RepoMode) -> std::path::PathBuf { + glob::glob( + paths::home() + .join(".cargo/registry/index/*") + .to_str() + .unwrap(), + ) + .unwrap() + .map(Result::unwrap) + .filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow)) + .next() + .unwrap() +} + +/// Find a checkout directory for bar, `shallow` or not. +fn find_bar_db(mode: RepoMode) -> std::path::PathBuf { + glob::glob(paths::home().join(".cargo/git/db/bar-*").to_str().unwrap()) + .unwrap() + .map(Result::unwrap) + .filter(|p| p.to_string_lossy().ends_with("-shallow") == matches!(mode, RepoMode::Shallow)) + .next() + .unwrap() + .to_owned() +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/glob_targets.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/glob_targets.rs new file mode 100644 index 000000000..ed292de31 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/glob_targets.rs @@ -0,0 +1,512 @@ +//! Tests for target filter flags with glob patterns. + +use cargo_test_support::prelude::*; +use cargo_test_support::{project, str, Project}; + +#[cargo_test] +fn build_example() { + full_project() + .cargo("build -v --example 'ex*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name example1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_bin() { + full_project() + .cargo("build -v --bin 'bi*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_bench() { + full_project() + .cargo("build -v --bench 'be*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name bench1 [..]` +[RUNNING] `rustc --crate-name bin2 [..]` +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_test() { + full_project() + .cargo("build -v --test 'te*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name bin2 [..]` +[RUNNING] `rustc --crate-name test1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn check_example() { + full_project() + .cargo("check -v --example 'ex*1'") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name example1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_bin() { + full_project() + .cargo("check -v --bin 'bi*1'") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_bench() { + full_project() + .cargo("check -v --bench 'be*1'") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bench1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_test() { + full_project() + .cargo("check -v --test 'te*1'") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn doc_bin() { + full_project() + .cargo("doc -v --bin 'bi*1'") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name bin1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bin1/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn fix_example() { + full_project() + .cargo("fix -v --example 'ex*1' --allow-no-vcs") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name example1 [..]` +[FIXING] examples/example1.rs +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fix_bin() { + full_project() + .cargo("fix -v --bin 'bi*1' --allow-no-vcs") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name bin1 [..]` +[FIXING] src/bin/bin1.rs +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fix_bench() { + full_project() + .cargo("fix -v --bench 'be*1' --allow-no-vcs") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name bench1 [..]` +[FIXING] benches/bench1.rs +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fix_test() { + full_project() + .cargo("fix -v --test 'te*1' --allow-no-vcs") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name test1 [..]` +[FIXING] tests/test1.rs +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn run_example_and_bin() { + let p = full_project(); + p.cargo("run -v --bin 'bi*1'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` does not support glob patterns on target selection + +"#]]) + .run(); + + p.cargo("run -v --example 'ex*1'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` does not support glob patterns on target selection + +"#]]) + .run(); +} + +#[cargo_test] +fn test_example() { + full_project() + .cargo("test -v --example 'ex*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name example1 [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/examples/example1-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn test_bin() { + full_project() + .cargo("test -v --bin 'bi*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/bin1-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn test_bench() { + full_project() + .cargo("test -v --bench 'be*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin2 [..]` +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name bench1 [..]` +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/bench1-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_test() { + full_project() + .cargo("test -v --test 'te*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test1 [..]` +[RUNNING] `rustc --crate-name bin1 [..]` +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name bin2 [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/test1-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn bench_example() { + full_project() + .cargo("bench -v --example 'ex*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name example1 [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/examples/example1-[HASH][EXE] --bench` + +"#]]) + .run(); +} + +#[cargo_test] +fn bench_bin() { + full_project() + .cargo("bench -v --bin 'bi*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/bin1-[HASH][EXE] --bench` + +"#]]) + .run(); +} + +#[cargo_test] +fn bench_bench() { + full_project() + .cargo("bench -v --bench 'be*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[RUNNING] `rustc --crate-name bin2 [..]` +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name bench1 [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/bench1-[HASH][EXE] --bench` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn bench_test() { + full_project() + .cargo("bench -v --test 'te*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin2 [..]` +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name test1 [..]` +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/test1-[HASH][EXE] --bench` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn install_example() { + full_project() + .cargo("install --path . --example 'ex*1'") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/example1[EXE] +[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `example1[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn install_bin() { + full_project() + .cargo("install --path . --bin 'bi*1'") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/bin1[EXE] +[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `bin1[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_example() { + full_project() + .cargo("rustdoc -v --example 'ex*1'") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name example1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/example1/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_bin() { + full_project() + .cargo("rustdoc -v --bin 'bi*1'") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name bin1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bin1/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_bench() { + full_project() + .cargo("rustdoc -v --bench 'be*1'") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name bench1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bench1/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_test() { + full_project() + .cargo("rustdoc -v --test 'te*1'") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc --edition=2015 --crate-type bin --crate-name test1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/test1/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_example() { + full_project() + .cargo("rustc -v --example 'ex*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name example1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_bin() { + full_project() + .cargo("rustc -v --bin 'bi*1'") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_bench() { + full_project() + .cargo("rustc -v --bench 'be*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[RUNNING] `rustc --crate-name bench1 [..]` +[RUNNING] `rustc --crate-name bin2 [..]` +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn rustc_test() { + full_project() + .cargo("rustc -v --test 'te*1'") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name bin1 [..]` +[RUNNING] `rustc --crate-name bin2 [..]` +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name test1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +fn full_project() -> Project { + project() + .file("examples/example1.rs", "fn main() { }") + .file("examples/example2.rs", "fn main() { }") + .file("benches/bench1.rs", "") + .file("benches/bench2.rs", "") + .file("tests/test1.rs", "") + .file("tests/test2.rs", "") + .file("src/main.rs", "fn main() { }") + .file("src/bin/bin1.rs", "fn main() { }") + .file("src/bin/bin2.rs", "fn main() { }") + .build() +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/global_cache_tracker.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/global_cache_tracker.rs new file mode 100644 index 000000000..045f34db2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/global_cache_tracker.rs @@ -0,0 +1,2141 @@ +//! Tests for last-use tracking and auto-gc. +//! +//! Cargo supports an environment variable called `__CARGO_TEST_LAST_USE_NOW` +//! to have cargo pretend that the current time is the given time (in seconds +//! since the unix epoch). This is used throughout these tests to simulate +//! what happens when time passes. The [`days_ago_unix`] and +//! [`months_ago_unix`] functions help with setting this value. + +use std::env; +use std::fmt::Write; +use std::path::Path; +use std::path::PathBuf; +use std::process::Stdio; +use std::sync::OnceLock; +use std::time::{Duration, SystemTime}; + +use cargo::core::global_cache_tracker::{self, DeferredGlobalLastUse, GlobalCacheTracker}; +use cargo::util::cache_lock::CacheLockMode; +use cargo::util::interning::InternedString; +use cargo::GlobalContext; +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Package, RegistryBuilder}; +use cargo_test_support::{ + basic_manifest, cargo_process, execs, git, process, project, retry, sleep_ms, str, + thread_wait_timeout, Execs, Project, +}; +use itertools::Itertools; + +use super::config::GlobalContextBuilder; + +/// Helper to create a simple `foo` project which depends on a registry +/// dependency called `bar`. +fn basic_foo_bar_project() -> Project { + Package::new("bar", "1.0.0").publish(); + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build() +} + +/// Helper to get the names of files in a directory as strings. +fn get_names(glob: &str) -> Vec { + let mut names: Vec<_> = glob::glob(paths::home().join(glob).to_str().unwrap()) + .unwrap() + .map(|p| p.unwrap().file_name().unwrap().to_str().unwrap().to_owned()) + .collect(); + names.sort(); + names +} + +fn get_registry_names(which: &str) -> Vec { + get_names(&format!(".cargo/registry/{which}/*/*")) +} + +fn get_index_names() -> Vec { + get_names(&format!(".cargo/registry/index/*")) +} + +fn get_git_db_names() -> Vec { + get_names(&format!(".cargo/git/db/*")) +} + +fn get_git_checkout_names(db_name: &str) -> Vec { + get_names(&format!(".cargo/git/checkouts/{db_name}/*")) +} + +fn days_ago(n: u64) -> SystemTime { + now() - Duration::from_secs(60 * 60 * 24 * n) +} + +fn now() -> SystemTime { + // This captures the time once to avoid potential time boundaries or + // inconsistencies affecting a test. For example, on a fast system + // `days_ago(1)` called twice in a row will return the same answer. + // However, on a slower system, or if the clock happens to flip over from + // one second to the next, then it would return different answers. This + // ensures that it always returns the same answer. + static START: OnceLock = OnceLock::new(); + *START.get_or_init(|| SystemTime::now()) +} + +/// Helper for simulating running cargo in the past. Use with the +/// `__CARGO_TEST_LAST_USE_NOW` environment variable. +fn days_ago_unix(n: u64) -> String { + days_ago(n) + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs() + .to_string() +} + +/// Helper for simulating running cargo in the past. Use with the +/// `__CARGO_TEST_LAST_USE_NOW` environment variable. +fn months_ago_unix(n: u64) -> String { + days_ago_unix(n * 30) +} + +/// Populates last-use database and the cache files. +/// +/// This makes it easier to more accurately specify exact sizes. Creating +/// specific sizes with `Package` is too difficult. +fn populate_cache( + gctx: &GlobalContext, + test_crates: &[(&str, u64, u64, u64)], +) -> (PathBuf, PathBuf) { + let cache_dir = paths::home().join(".cargo/registry/cache/example.com-a6c4a5adcb232b9a"); + let src_dir = paths::home().join(".cargo/registry/src/example.com-a6c4a5adcb232b9a"); + + GlobalCacheTracker::db_path(&gctx) + .into_path_unlocked() + .rm_rf(); + + let _lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let mut tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let mut deferred = DeferredGlobalLastUse::new(); + + cache_dir.rm_rf(); + cache_dir.mkdir_p(); + src_dir.rm_rf(); + src_dir.mkdir_p(); + paths::home() + .join(".cargo/registry/index/example.com-a6c4a5adcb232b9a") + .mkdir_p(); + let mut create = |name: &str, age, crate_size: u64, src_size: u64| { + let crate_filename = InternedString::new(&format!("{name}.crate")); + deferred.mark_registry_crate_used_stamp( + global_cache_tracker::RegistryCrate { + encoded_registry_name: "example.com-a6c4a5adcb232b9a".into(), + crate_filename, + size: crate_size, + }, + Some(&days_ago(age)), + ); + deferred.mark_registry_src_used_stamp( + global_cache_tracker::RegistrySrc { + encoded_registry_name: "example.com-a6c4a5adcb232b9a".into(), + package_dir: name.into(), + size: Some(src_size), + }, + Some(&days_ago(age)), + ); + std::fs::write( + cache_dir.join(crate_filename), + "x".repeat(crate_size as usize), + ) + .unwrap(); + let path = src_dir.join(name); + path.mkdir_p(); + std::fs::write(path.join("data"), "x".repeat(src_size as usize)).unwrap() + }; + + for (name, age, crate_size, src_size) in test_crates { + create(name, *age, *crate_size, *src_size); + } + deferred.save(&mut tracker).unwrap(); + + (cache_dir, src_dir) +} + +/// Returns an `Execs` that will run the rustup `cargo` proxy from the global +/// system's cargo home directory. +fn rustup_cargo() -> Execs { + // Modify the PATH to ensure that `cargo` and `rustc` comes from + // CARGO_HOME. This is necessary because cargo adds the "deps" directory + // into PATH on Windows, which points to the wrong cargo. + let real_cargo_home_bin = Path::new(&std::env::var_os("CARGO_HOME").unwrap()).join("bin"); + let mut paths = vec![real_cargo_home_bin]; + paths.extend(env::split_paths(&env::var_os("PATH").unwrap_or_default())); + let path = env::join_paths(paths).unwrap(); + let mut e = execs().with_process_builder(process("cargo")); + e.env("PATH", path); + e +} + +#[cargo_test] +fn auto_gc_gated() { + // Requires -Zgc to run auto-gc. + let p = basic_foo_bar_project(); + p.cargo("check") + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + // Check that it created a database. + let gctx = GlobalContextBuilder::new().build(); + assert!(GlobalCacheTracker::db_path(&gctx) + .into_path_unlocked() + .exists()); + assert_eq!(get_index_names().len(), 1); + + // Again in the future, shouldn't auto-gc. + p.cargo("check").run(); + assert_eq!(get_index_names().len(), 1); +} + +#[cargo_test] +fn clean_gc_gated() { + cargo_process("clean gc") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `cargo clean gc` command is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels. +See https://github.com/rust-lang/cargo/issues/12633 for more information about the `cargo clean gc` command. + +"#]] + ) + .run(); +} + +#[cargo_test] +fn implies_source() { + // Checks that when a src, crate, or checkout is marked as used, the + // corresponding index or git db also gets marked as used. + let gctx = GlobalContextBuilder::new().build(); + let _lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let mut deferred = DeferredGlobalLastUse::new(); + let mut tracker = GlobalCacheTracker::new(&gctx).unwrap(); + + deferred.mark_registry_crate_used(global_cache_tracker::RegistryCrate { + encoded_registry_name: "example.com-a6c4a5adcb232b9a".into(), + crate_filename: "regex-1.8.4.crate".into(), + size: 123, + }); + deferred.mark_registry_src_used(global_cache_tracker::RegistrySrc { + encoded_registry_name: "index.crates.io-6f17d22bba15001f".into(), + package_dir: "rand-0.8.5".into(), + size: None, + }); + deferred.mark_git_checkout_used(global_cache_tracker::GitCheckout { + encoded_git_name: "cargo-e7ff1db891893a9e".into(), + short_name: "f0a4ee0".into(), + size: None, + }); + deferred.save(&mut tracker).unwrap(); + + let mut indexes = tracker.registry_index_all().unwrap(); + assert_eq!(indexes.len(), 2); + indexes.sort_by(|a, b| a.0.encoded_registry_name.cmp(&b.0.encoded_registry_name)); + assert_eq!( + indexes[0].0.encoded_registry_name, + "example.com-a6c4a5adcb232b9a" + ); + assert_eq!( + indexes[1].0.encoded_registry_name, + "index.crates.io-6f17d22bba15001f" + ); + + let dbs = tracker.git_db_all().unwrap(); + assert_eq!(dbs.len(), 1); + assert_eq!(dbs[0].0.encoded_git_name, "cargo-e7ff1db891893a9e"); +} + +#[cargo_test] +fn auto_gc_defaults() { + // Checks that the auto-gc deletes old entries, and leaves new ones intact. + Package::new("old", "1.0.0").publish(); + Package::new("new", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + old = "1.0" + new = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + // Populate the last-use data. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + assert_eq!(get_registry_names("src"), ["new-1.0.0", "old-1.0.0"]); + assert_eq!( + get_registry_names("cache"), + ["new-1.0.0.crate", "old-1.0.0.crate"] + ); + + // Run again with just one package. Make sure the old src gets deleted, + // but .crate does not. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + new = "1.0" + "#, + ); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(2)) + .run(); + assert_eq!(get_registry_names("src"), ["new-1.0.0"]); + assert_eq!( + get_registry_names("cache"), + ["new-1.0.0.crate", "old-1.0.0.crate"] + ); + + // Run again after the .crate should have aged out. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + assert_eq!(get_registry_names("src"), ["new-1.0.0"]); + assert_eq!(get_registry_names("cache"), ["new-1.0.0.crate"]); +} + +#[cargo_test] +fn auto_gc_config() { + // Can configure auto gc settings. + Package::new("old", "1.0.0").publish(); + Package::new("new", "1.0.0").publish(); + let p = project() + .file( + ".cargo/config.toml", + r#" + [gc.auto] + frequency = "always" + max-src-age = "1 day" + max-crate-age = "3 days" + max-index-age = "3 days" + max-git-co-age = "1 day" + max-git-db-age = "3 days" + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + old = "1.0" + new = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + // Populate the last-use data. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(4)) + .run(); + assert_eq!(get_registry_names("src"), ["new-1.0.0", "old-1.0.0"]); + assert_eq!( + get_registry_names("cache"), + ["new-1.0.0.crate", "old-1.0.0.crate"] + ); + + // Run again with just one package. Make sure the old src gets deleted, + // but .crate does not. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + new = "1.0" + "#, + ); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2)) + .run(); + assert_eq!(get_registry_names("src"), ["new-1.0.0"]); + assert_eq!( + get_registry_names("cache"), + ["new-1.0.0.crate", "old-1.0.0.crate"] + ); + + // Run again after the .crate should have aged out. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + assert_eq!(get_registry_names("src"), ["new-1.0.0"]); + assert_eq!(get_registry_names("cache"), ["new-1.0.0.crate"]); +} + +#[cargo_test] +fn frequency() { + // gc.auto.frequency settings + let p = basic_foo_bar_project(); + p.change_file( + ".cargo/config.toml", + r#" + [gc.auto] + frequency = "never" + "#, + ); + // Populate data in the past. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + assert_eq!(get_index_names().len(), 1); + assert_eq!(get_registry_names("src"), ["bar-1.0.0"]); + assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]); + + p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0")); + + // Try after the default expiration time, with "never" it shouldn't gc. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + assert_eq!(get_index_names().len(), 1); + assert_eq!(get_registry_names("src"), ["bar-1.0.0"]); + assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]); + + // Try again with a setting that allows it to run. + p.cargo("check -Zgc") + .env("CARGO_GC_AUTO_FREQUENCY", "1 day") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + assert_eq!(get_index_names().len(), 0); + assert_eq!(get_registry_names("src").len(), 0); + assert_eq!(get_registry_names("cache").len(), 0); +} + +#[cargo_test] +fn auto_gc_index() { + // Deletes the index if it hasn't been used in a while. + let p = basic_foo_bar_project(); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + assert_eq!(get_index_names().len(), 1); + + // Make sure it stays within the time frame. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(2)) + .run(); + assert_eq!(get_index_names().len(), 1); + + // After it expires, it should be deleted. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + assert_eq!(get_index_names().len(), 0); +} + +#[cargo_test] +fn auto_gc_git() { + // auto-gc should delete git checkouts and dbs. + + // Returns the short git name of a checkout. + let short_id = |repo: &git2::Repository| -> String { + let head = repo.revparse_single("HEAD").unwrap(); + let short_id = head.short_id().unwrap(); + short_id.as_str().unwrap().to_owned() + }; + + // Set up a git dependency and fetch it and populate the database, + // 6 months in the past. + let (git_project, git_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(6)) + .run(); + let db_names = get_git_db_names(); + assert_eq!(db_names.len(), 1); + let first_short_oid = short_id(&git_repo); + assert_eq!( + get_git_checkout_names(&db_names[0]), + [first_short_oid.clone()] + ); + + // Use a new git checkout, should keep both. + git_project.change_file("src/lib.rs", "// modified"); + git::add(&git_repo); + git::commit(&git_repo); + p.cargo("update -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(6)) + .run(); + assert_eq!(get_git_db_names().len(), 1); + let second_short_oid = short_id(&git_repo); + let mut both = vec![first_short_oid, second_short_oid.clone()]; + both.sort(); + assert_eq!(get_git_checkout_names(&db_names[0]), both); + + // In the future, using the second checkout should delete the first. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + assert_eq!(get_git_db_names().len(), 1); + assert_eq!( + get_git_checkout_names(&db_names[0]), + [second_short_oid.clone()] + ); + + // After three months, the db should get deleted. + p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0")); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + assert_eq!(get_git_db_names().len(), 0); + assert_eq!(get_git_checkout_names(&db_names[0]).len(), 0); +} + +#[cargo_test] +fn auto_gc_various_commands() { + // Checks that auto gc works with a variety of commands. + // + // Auto-gc is only run on a subset of commands. Generally it is run on + // commands that are already doing a lot of work, or heavily involve the + // use of the registry. + Package::new("bar", "1.0.0").publish(); + let cmds = ["check", "fetch"]; + for cmd in cmds { + eprintln!("checking command {cmd}"); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + // Populate the last-use data. + p.cargo(cmd) + .arg("-Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + let gctx = GlobalContextBuilder::new().build(); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let indexes = tracker.registry_index_all().unwrap(); + assert_eq!(indexes.len(), 1); + let crates = tracker.registry_crate_all().unwrap(); + assert_eq!(crates.len(), 1); + let srcs = tracker.registry_src_all().unwrap(); + assert_eq!(srcs.len(), 1); + drop(lock); + + // After everything is aged out, it should all be deleted. + p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0")); + p.cargo(cmd) + .arg("-Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let indexes = tracker.registry_index_all().unwrap(); + assert_eq!(indexes.len(), 0); + let crates = tracker.registry_crate_all().unwrap(); + assert_eq!(crates.len(), 0); + let srcs = tracker.registry_src_all().unwrap(); + assert_eq!(srcs.len(), 0); + drop(tracker); + drop(lock); + paths::home().join(".cargo/registry").rm_rf(); + GlobalCacheTracker::db_path(&gctx) + .into_path_unlocked() + .rm_rf(); + } +} + +#[cargo_test] +fn updates_last_use_various_commands() { + // Checks that last-use tracking is updated by various commands. + // + // Not *all* commands update the index tracking, even though they + // technically involve reading the index. There isn't a convenient place + // to ensure it gets saved while avoiding saving too often in other + // commands. For the most part, this should be fine, since these commands + // usually aren't run without running one of the commands that does save + // the tracking. Some of the commands are: + // + // - login, owner, yank, search + // - report future-incompatibilities + // - package --no-verify + // - fetch --locked + Package::new("bar", "1.0.0").publish(); + let cmds = [ + // name, expected_crates (0=doesn't download) + ("check", 1), + ("fetch", 1), + ("tree", 1), + ("generate-lockfile", 0), + ("update", 0), + ("metadata", 1), + ("vendor --respect-source-config", 1), + ]; + for (cmd, expected_crates) in cmds { + eprintln!("checking command {cmd}"); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + // Populate the last-use data. + p.cargo(cmd) + .arg("-Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + let gctx = GlobalContextBuilder::new().build(); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let indexes = tracker.registry_index_all().unwrap(); + assert_eq!(indexes.len(), 1); + let crates = tracker.registry_crate_all().unwrap(); + assert_eq!(crates.len(), expected_crates); + let srcs = tracker.registry_src_all().unwrap(); + assert_eq!(srcs.len(), expected_crates); + drop(tracker); + drop(lock); + paths::home().join(".cargo/registry").rm_rf(); + GlobalCacheTracker::db_path(&gctx) + .into_path_unlocked() + .rm_rf(); + } +} + +#[cargo_test] +fn both_git_and_http_index_cleans() { + // Checks that either the git or http index cache gets cleaned. + let _crates_io = RegistryBuilder::new().build(); + let _alternative = RegistryBuilder::new().alternative().http_index().build(); + Package::new("from_git", "1.0.0").publish(); + Package::new("from_http", "1.0.0") + .alternative(true) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + from_git = "1.0" + from_http = { version = "1.0", registry = "alternative" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + let gctx = GlobalContextBuilder::new().build(); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let indexes = tracker.registry_index_all().unwrap(); + assert_eq!(indexes.len(), 2); + assert_eq!(get_index_names().len(), 2); + drop(lock); + + // Running in the future without these indexes should delete them. + p.change_file("Cargo.toml", &basic_manifest("foo", "0.2.0")); + p.cargo("clean gc -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let indexes = tracker.registry_index_all().unwrap(); + assert_eq!(indexes.len(), 0); + assert_eq!(get_index_names().len(), 0); + drop(lock); +} + +#[cargo_test] +fn clean_gc_dry_run() { + // Basic `clean --gc --dry-run` test. + let p = basic_foo_bar_project(); + // Populate the last-use data. + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + + let registry_root = paths::home().join(".cargo/registry"); + let glob_registry = |name| -> PathBuf { + let mut paths: Vec<_> = glob::glob(registry_root.join(name).join("*").to_str().unwrap()) + .unwrap() + .map(|p| p.unwrap()) + .collect(); + assert_eq!(paths.len(), 1); + paths.pop().unwrap() + }; + let index = glob_registry("index").ls_r(); + let src = glob_registry("src").ls_r(); + let cache = glob_registry("cache").ls_r(); + let mut expected_files = index + .iter() + .chain(src.iter()) + .chain(cache.iter()) + .map(|p| p.to_str().unwrap()) + .join("\n"); + expected_files.push_str("\n"); + let expected_files = snapbox::filter::normalize_paths(&expected_files); + let expected_files = assert_e2e().redactions().redact(&expected_files); + + p.cargo("clean gc --dry-run -v -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stdout_data(expected_files.as_str().unordered()) + .with_stderr_data(str![[r#" +[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total +[WARNING] no files deleted due to --dry-run + +"#]]) + .run(); + + // Again, make sure the information is still tracked. + p.cargo("clean gc --dry-run -v -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stdout_data(expected_files.as_str().unordered()) + .with_stderr_data(str![[r#" +[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total +[WARNING] no files deleted due to --dry-run + +"#]]) + .run(); +} + +#[cargo_test] +fn clean_default_gc() { + // `clean gc` without options should also gc + let p = basic_foo_bar_project(); + // Populate the last-use data. + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + p.cargo("clean gc -v -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data( + str![[r#" +[REMOVING] [ROOT]/home/.cargo/registry/index/-[HASH] +[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH] +[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH] +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn tracks_sizes() { + // Checks that sizes are properly tracked in the db. + Package::new("dep1", "1.0.0") + .file("src/lib.rs", "") + .publish(); + Package::new("dep2", "1.0.0") + .file("src/lib.rs", "") + .file("data", &"abcdefghijklmnopqrstuvwxyz".repeat(1000)) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep1 = "1.0" + dep2 = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + + // Check that the crate sizes are the same as on disk. + let gctx = GlobalContextBuilder::new().build(); + let _lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let mut crates = tracker.registry_crate_all().unwrap(); + crates.sort_by(|a, b| a.0.crate_filename.cmp(&b.0.crate_filename)); + let db_sizes: Vec<_> = crates.iter().map(|c| c.0.size).collect(); + + let mut actual: Vec<_> = p + .glob(paths::home().join(".cargo/registry/cache/*/*")) + .map(|p| p.unwrap()) + .collect(); + actual.sort(); + let actual_sizes: Vec<_> = actual + .iter() + .map(|path| std::fs::metadata(path).unwrap().len()) + .collect(); + assert_eq!(db_sizes, actual_sizes); + + // Also check the src sizes are computed. + let mut srcs = tracker.registry_src_all().unwrap(); + srcs.sort_by(|a, b| a.0.package_dir.cmp(&b.0.package_dir)); + let db_sizes: Vec<_> = srcs.iter().map(|c| c.0.size.unwrap()).collect(); + let mut actual: Vec<_> = p + .glob(paths::home().join(".cargo/registry/src/*/*")) + .map(|p| p.unwrap()) + .collect(); + actual.sort(); + // .cargo-ok is not tracked in the size. + actual.iter().for_each(|p| p.join(".cargo-ok").rm_rf()); + let actual_sizes: Vec<_> = actual + .iter() + .map(|path| cargo_util::du(path, &[]).unwrap()) + .collect(); + assert_eq!(db_sizes, actual_sizes); + assert!(db_sizes[1] > 26000); +} + +#[cargo_test] +fn max_size() { + // Checks --max-crate-size and --max-src-size with various cleaning thresholds. + let gctx = GlobalContextBuilder::new().build(); + + let test_crates = [ + // name, age, crate_size, src_size + ("a-1.0.0", 5, 1, 1), + ("b-1.0.0", 6, 2, 2), + ("c-1.0.0", 3, 3, 3), + ("d-1.0.0", 2, 4, 4), + ("e-1.0.0", 2, 5, 5), + ("f-1.0.0", 9, 6, 6), + ("g-1.0.0", 1, 1, 1), + ]; + + // Determine the order things get deleted so they can be verified. + let mut names_by_timestamp: Vec<_> = test_crates + .iter() + .map(|(name, age, _, _)| (days_ago_unix(*age), name)) + .collect(); + names_by_timestamp.sort(); + let names_by_timestamp: Vec<_> = names_by_timestamp + .into_iter() + .map(|(_, name)| name) + .collect(); + + // This exercises the different boundary conditions. + for (clean_size, files) in [ + (22, 0), + (21, 1), + (16, 1), + (15, 2), + (14, 2), + (13, 3), + (12, 4), + (10, 4), + (9, 5), + (6, 5), + (5, 6), + (1, 6), + (0, 7), + ] { + let (removed, kept) = names_by_timestamp.split_at(files); + // --max-crate-size + let (cache_dir, src_dir) = populate_cache(&gctx, &test_crates); + let mut stderr = String::new(); + for name in removed { + writeln!(stderr, "[REMOVING] [..]{name}.crate").unwrap(); + } + let total_display = if removed.is_empty() { + "" + } else { + ", [FILE_SIZE]B total" + }; + let files_display = if files == 0 { + "0 files" + } else if files == 1 { + "1 file" + } else { + "[FILE_NUM] files" + }; + writeln!(stderr, "[REMOVED] {files_display}{total_display}").unwrap(); + cargo_process(&format!("clean gc -Zgc -v --max-crate-size={clean_size}")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(stderr.unordered()) + .run(); + for name in kept { + assert!(cache_dir.join(format!("{name}.crate")).exists()); + } + for name in removed { + assert!(!cache_dir.join(format!("{name}.crate")).exists()); + } + + // --max-src-size + populate_cache(&gctx, &test_crates); + let mut stderr = String::new(); + for name in removed { + writeln!(stderr, "[REMOVING] [..]{name}").unwrap(); + } + let total_display = if removed.is_empty() { + "" + } else { + ", [FILE_SIZE]B total" + }; + writeln!(stderr, "[REMOVED] {files_display}{total_display}").unwrap(); + cargo_process(&format!("clean gc -Zgc -v --max-src-size={clean_size}")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(stderr.unordered()) + .run(); + for name in kept { + assert!(src_dir.join(name).exists()); + } + for name in removed { + assert!(!src_dir.join(name).exists()); + } + } +} + +#[cargo_test] +fn max_size_untracked_crate() { + // When a .crate file exists from an older version of cargo that did not + // track sizes, `clean --max-crate-size` should populate the db with the + // sizes. + let gctx = GlobalContextBuilder::new().build(); + let cache = paths::home().join(".cargo/registry/cache/example.com-a6c4a5adcb232b9a"); + cache.mkdir_p(); + paths::home() + .join(".cargo/registry/index/example.com-a6c4a5adcb232b9a") + .mkdir_p(); + // Create the `.crate files. + let test_crates = [ + // name, size + ("a-1.0.0.crate", 1234), + ("b-1.0.0.crate", 42), + ("c-1.0.0.crate", 0), + ]; + for (name, size) in test_crates { + std::fs::write(cache.join(name), "x".repeat(size as usize)).unwrap() + } + // This should scan the directory and populate the db with the size information. + cargo_process("clean gc -Zgc -v --max-crate-size=100000") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVED] 0 files + +"#]]) + .run(); + // Check that it stored the size data. + let _lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let crates = tracker.registry_crate_all().unwrap(); + let mut actual: Vec<_> = crates + .iter() + .map(|(rc, _time)| (rc.crate_filename.as_str(), rc.size)) + .collect(); + actual.sort(); + assert_eq!(test_crates, actual.as_slice()); +} + +/// Helper to prepare the max-size test. +fn max_size_untracked_prepare() -> (GlobalContext, Project) { + // First, publish and download a dependency. + let p = basic_foo_bar_project(); + p.cargo("fetch").run(); + // Pretend it was an older version that did not track last-use. + let gctx = GlobalContextBuilder::new().build(); + GlobalCacheTracker::db_path(&gctx) + .into_path_unlocked() + .rm_rf(); + (gctx, p) +} + +/// Helper to verify the max-size test. +fn max_size_untracked_verify(gctx: &GlobalContext) { + let actual: Vec<_> = glob::glob( + paths::home() + .join(".cargo/registry/src/*/*") + .to_str() + .unwrap(), + ) + .unwrap() + .map(|p| p.unwrap()) + .collect(); + assert_eq!(actual.len(), 1); + let actual_size = cargo_util::du(&actual[0], &[]).unwrap(); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let srcs = tracker.registry_src_all().unwrap(); + assert_eq!(srcs.len(), 1); + assert_eq!(srcs[0].0.size, Some(actual_size)); + drop(lock); +} + +#[cargo_test] +fn max_size_untracked_src_from_use() { + // When a src directory exists from an older version of cargo that did not + // track sizes, doing a build should populate the db with an entry with an + // unknown size. `clean --max-src-size` should then fix the size. + let (gctx, p) = max_size_untracked_prepare(); + + // Run a command that will update the db with an unknown src size. + p.cargo("tree -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + // Check that it is None. + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let srcs = tracker.registry_src_all().unwrap(); + assert_eq!(srcs.len(), 1); + assert_eq!(srcs[0].0.size, None); + drop(lock); + + // Fix the size. + p.cargo("clean gc -v --max-src-size=10000 -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVED] 0 files + +"#]]) + .run(); + max_size_untracked_verify(&gctx); +} + +#[cargo_test] +fn max_size_untracked_src_from_clean() { + // When a src directory exists from an older version of cargo that did not + // track sizes, `clean --max-src-size` should populate the db with the + // sizes. + let (gctx, p) = max_size_untracked_prepare(); + + // Clean should scan the src and update the db. + p.cargo("clean gc -v --max-src-size=10000 -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVED] 0 files + +"#]]) + .run(); + max_size_untracked_verify(&gctx); +} + +#[cargo_test] +fn max_download_size() { + // --max-download-size + // + // This creates some sample crates of specific sizes, and then tries + // deleting at various specific size thresholds that exercise different + // edge conditions. + let gctx = GlobalContextBuilder::new().build(); + + let test_crates = [ + // name, age, crate_size, src_size + ("d-1.0.0", 4, 4, 5), + ("c-1.0.0", 3, 3, 3), + ("a-1.0.0", 1, 2, 5), + ("b-1.0.0", 1, 1, 7), + ]; + + for (max_size, num_deleted, files_deleted) in [ + (30, 0, 0), + (29, 1, 1), + (24, 2, 2), + (20, 3, 3), + (1, 7, 7), + (0, 8, 8), + ] { + populate_cache(&gctx, &test_crates); + // Determine the order things will be deleted. + let delete_order: Vec = test_crates + .iter() + .flat_map(|(name, _, _, _)| [name.to_string(), format!("{name}.crate")]) + .collect(); + let (removed, _kept) = delete_order.split_at(num_deleted); + let mut stderr = String::new(); + for name in removed { + writeln!(stderr, "[REMOVING] [..]{name}").unwrap(); + } + let files_display = if files_deleted == 0 { + "0 files" + } else if files_deleted == 1 { + "1 file" + } else { + "[FILE_NUM] files" + }; + let total_display = if removed.is_empty() { + "" + } else { + ", [FILE_SIZE]B total" + }; + writeln!(stderr, "[REMOVED] {files_display}{total_display}",).unwrap(); + cargo_process(&format!("clean gc -Zgc -v --max-download-size={max_size}")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(stderr.unordered()) + .run(); + } +} + +#[cargo_test] +fn package_cache_lock_during_build() { + // Verifies that a shared lock is held during a build. Resolution and + // downloads should be OK while that is held, but mutation should block. + // + // This works by launching a build with a build script that will pause. + // Then it performs other cargo commands and verifies their behavior. + Package::new("bar", "1.0.0").publish(); + let p_foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { + std::fs::write("blocking", "").unwrap(); + let path = std::path::Path::new("ready"); + loop { + if path.exists() { + break; + } else { + std::thread::sleep(std::time::Duration::from_millis(100)) + } + } + } + "#, + ) + .build(); + let p_foo2 = project() + .at("foo2") + .file( + "Cargo.toml", + r#" + [package] + name = "foo2" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Start a build that will pause once the build starts. + let mut foo_child = p_foo + .cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .build_command() + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + // Wait for it to enter build script. + retry(100, || p_foo.root().join("blocking").exists().then_some(())); + + // Start a build with a different target directory. It should not block, + // even though it gets a download lock, and then a shared lock. + // + // Also verify that auto-gc gets disabled. + p_foo2 + .cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("CARGO_GC_AUTO_FREQUENCY", "always") + .env("CARGO_LOG", "gc=debug") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version + [..]s DEBUG gc: unable to acquire mutate lock, auto gc disabled +[CHECKING] bar v1.0.0 +[CHECKING] foo2 v0.1.0 ([ROOT]/foo2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Ensure that the first build really blocked. + assert!(matches!(foo_child.try_wait(), Ok(None))); + + // Cleaning while a command is running should block. + let mut clean_cmd = p_foo2 + .cargo("clean gc --max-download-size=0 -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .build_command(); + clean_cmd.stderr(Stdio::piped()); + let mut clean_child = clean_cmd.spawn().unwrap(); + + // Give the clean command a chance to finish (it shouldn't). + sleep_ms(500); + // They should both still be running. + assert!(matches!(foo_child.try_wait(), Ok(None))); + assert!(matches!(clean_child.try_wait(), Ok(None))); + + // Let the original build finish. + p_foo.change_file("ready", ""); + + // Wait for clean to finish. + let thread = std::thread::spawn(|| clean_child.wait_with_output().unwrap()); + let output = thread_wait_timeout(100, thread); + assert!(output.status.success()); + // Validate the output of the clean. + execs() + .with_stderr_data(str![[r#" +[BLOCKING] waiting for file lock on package cache mutation +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run_output(&output); +} + +#[cargo_test] +fn read_only_locking_auto_gc() { + // Tests the behavior for auto-gc on a read-only directory. + let p = basic_foo_bar_project(); + // Populate cache. + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + let cargo_home = paths::home().join(".cargo"); + let mut perms = std::fs::metadata(&cargo_home).unwrap().permissions(); + // Test when it can't update auto-gc db. + perms.set_readonly(true); + std::fs::set_permissions(&cargo_home, perms.clone()).unwrap(); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // Try again without the last-use existing (such as if the cache was + // populated by an older version of cargo). + perms.set_readonly(false); + std::fs::set_permissions(&cargo_home, perms.clone()).unwrap(); + let gctx = GlobalContextBuilder::new().build(); + GlobalCacheTracker::db_path(&gctx) + .into_path_unlocked() + .rm_rf(); + perms.set_readonly(true); + std::fs::set_permissions(&cargo_home, perms.clone()).unwrap(); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + perms.set_readonly(false); + std::fs::set_permissions(&cargo_home, perms).unwrap(); +} + +#[cargo_test] +fn delete_index_also_deletes_crates() { + // Checks that when an index is delete that src and cache directories also get deleted. + let p = basic_foo_bar_project(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + + assert_eq!(get_registry_names("src"), ["bar-1.0.0"]); + assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]); + + p.cargo("clean gc") + .arg("--max-index-age=0 days") + .arg("-Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + + assert_eq!(get_registry_names("src").len(), 0); + assert_eq!(get_registry_names("cache").len(), 0); +} + +#[cargo_test] +fn clean_syncs_missing_files() { + // When files go missing in the cache, clean operations that need to track + // the size should also remove them from the database. + Package::new("bar", "1.0.0").publish(); + Package::new("baz", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + baz = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + + // Verify things are tracked. + let gctx = GlobalContextBuilder::new().build(); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&gctx).unwrap(); + let crates = tracker.registry_crate_all().unwrap(); + assert_eq!(crates.len(), 2); + let srcs = tracker.registry_src_all().unwrap(); + assert_eq!(srcs.len(), 2); + drop(lock); + + // Remove the files. + for pattern in [ + ".cargo/registry/cache/*/bar-1.0.0.crate", + ".cargo/registry/src/*/bar-1.0.0", + ] { + p.glob(paths::home().join(pattern)) + .map(|p| p.unwrap()) + .next() + .unwrap() + .rm_rf(); + } + + // Clean should update the db. + p.cargo("clean gc -v --max-download-size=1GB -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVED] 0 files + +"#]]) + .run(); + + // Verify + let crates = tracker.registry_crate_all().unwrap(); + assert_eq!(crates.len(), 1); + let srcs = tracker.registry_src_all().unwrap(); + assert_eq!(srcs.len(), 1); +} + +#[cargo_test] +fn offline_doesnt_auto_gc() { + // When running offline, auto-gc shouldn't run. + let p = basic_foo_bar_project(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + // Remove the dependency. + p.change_file("Cargo.toml", &basic_manifest("foo", "0.1.0")); + // Run offline, make sure it doesn't delete anything + p.cargo("check --offline -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_eq!(get_registry_names("src"), ["bar-1.0.0"]); + assert_eq!(get_registry_names("cache"), ["bar-1.0.0.crate"]); + // Run online, make sure auto-gc runs. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert_eq!(get_registry_names("src"), &[] as &[String]); + assert_eq!(get_registry_names("cache"), &[] as &[String]); +} + +#[cargo_test] +fn can_handle_future_schema() -> anyhow::Result<()> { + // It should work when a future version of cargo has made schema changes + // to the database. + let p = basic_foo_bar_project(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + // Modify the schema to pretend this is done by a future version of cargo. + let gctx = GlobalContextBuilder::new().build(); + let db_path = GlobalCacheTracker::db_path(&gctx).into_path_unlocked(); + let conn = rusqlite::Connection::open(&db_path)?; + let user_version: u32 = + conn.query_row("SELECT user_version FROM pragma_user_version", [], |row| { + row.get(0) + })?; + conn.execute("ALTER TABLE global_data ADD COLUMN foo DEFAULT 123", [])?; + conn.pragma_update(None, "user_version", &(user_version + 1))?; + drop(conn); + // Verify it doesn't blow up. + p.cargo("clean gc --max-download-size=0 -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + Ok(()) +} + +#[cargo_test] +fn clean_max_git_age() { + // --max-git-*-age flags + let (git_a, git_a_repo) = git::new_repo("git_a", |p| { + p.file("Cargo.toml", &basic_manifest("git_a", "1.0.0")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + git_a = {{ git = '{}' }} + "#, + git_a.url() + ), + ) + .file("src/lib.rs", "") + .build(); + // Populate last-use tracking. + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(4)) + .run(); + // Update git_a to create a separate checkout. + git_a.change_file("src/lib.rs", "// test"); + git::add(&git_a_repo); + git::commit(&git_a_repo); + // Update last-use tracking, where the first git checkout will stay "old". + p.cargo("update -p git_a -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2)) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/git_a` +[LOCKING] 1 package to latest compatible version +[UPDATING] git_a v1.0.0 ([ROOTURL]/git_a#[..]) -> #[..] + +"#]]) + .run(); + + let db_names = get_git_db_names(); + assert_eq!(db_names.len(), 1); + let db_name = &db_names[0]; + let co_names = get_git_checkout_names(&db_name); + assert_eq!(co_names.len(), 2); + + // Delete the first checkout + p.cargo("clean gc -v -Zgc") + .arg("--max-git-co-age=3 days") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[HASH]/[..] +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + + let db_names = get_git_db_names(); + assert_eq!(db_names.len(), 1); + let co_names = get_git_checkout_names(&db_name); + assert_eq!(co_names.len(), 1); + + // delete the second checkout + p.cargo("clean gc -v -Zgc") + .arg("--max-git-co-age=0 days") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[HASH]/[..] +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + + let db_names = get_git_db_names(); + assert_eq!(db_names.len(), 1); + let co_names = get_git_checkout_names(&db_name); + assert_eq!(co_names.len(), 0); + + // delete the db + p.cargo("clean gc -v -Zgc") + .arg("--max-git-db-age=1 days") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/db/git_a-[HASH] +[REMOVING] [ROOT]/home/.cargo/git/checkouts/git_a-[HASH] +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + + let db_names = get_git_db_names(); + assert_eq!(db_names.len(), 0); + let co_names = get_git_checkout_names(&db_name); + assert_eq!(co_names.len(), 0); +} + +#[cargo_test] +fn clean_max_src_crate_age() { + // --max-src-age and --max-crate-age flags + let p = basic_foo_bar_project(); + // Populate last-use tracking. + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(4)) + .run(); + // Update bar to create a separate copy with a different timestamp. + Package::new("bar", "1.0.1").publish(); + p.cargo("update -p bar -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2)) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v1.0.0 -> v1.0.1 + +"#]]) + .run(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2)) + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.1 (registry `dummy-registry`) + +"#]]) + .run(); + + assert_eq!(get_registry_names("src"), ["bar-1.0.0", "bar-1.0.1"]); + assert_eq!( + get_registry_names("cache"), + ["bar-1.0.0.crate", "bar-1.0.1.crate"] + ); + + // Delete the old src. + p.cargo("clean gc -v -Zgc") + .arg("--max-src-age=3 days") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0 +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + + // delete the second src + p.cargo("clean gc -v -Zgc") + .arg("--max-src-age=0 days") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.1 +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + + // delete the old crate + p.cargo("clean gc -v -Zgc") + .arg("--max-crate-age=3 days") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH]/bar-1.0.0.crate +[REMOVED] 1 file, [FILE_SIZE]B total + +"#]]) + .run(); + + // delete the seecond crate + p.cargo("clean gc -v -Zgc") + .arg("--max-crate-age=0 days") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH]/bar-1.0.1.crate +[REMOVED] 1 file, [FILE_SIZE]B total + +"#]]) + .run(); +} + +#[cargo_test] +fn clean_max_git_size() { + // clean --max-git-size + // + // Creates two checkouts. The sets a size threshold to delete one. And + // then with 0 max size to delete everything. + let (git_project, git_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + // Fetch and populate db. + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(3)) + .run(); + + // Figure out the name of the first checkout. + let git_root = paths::home().join(".cargo/git"); + let db_names = get_git_db_names(); + assert_eq!(db_names.len(), 1); + let db_name = &db_names[0]; + let co_names = get_git_checkout_names(&db_name); + assert_eq!(co_names.len(), 1); + let first_co_name = &co_names[0]; + + // Make an update and create a new checkout. + git_project.change_file("src/lib.rs", "// modified"); + git::add(&git_repo); + git::commit(&git_repo); + p.cargo("update -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + // Use a different time so that the first checkout timestamp is less + // than the second. + .env("__CARGO_TEST_LAST_USE_NOW", days_ago_unix(2)) + .run(); + + // Figure out the threshold to use. + let mut co_names = get_git_checkout_names(&db_name); + assert_eq!(co_names.len(), 2); + co_names.retain(|name| name != first_co_name); + assert_eq!(co_names.len(), 1); + let second_co_name = &co_names[0]; + let second_co_path = git_root + .join("checkouts") + .join(db_name) + .join(second_co_name); + let second_co_size = cargo_util::du(&second_co_path, &["!.git"]).unwrap(); + + let db_size = cargo_util::du(&git_root.join("db").join(db_name), &[]).unwrap(); + + let threshold = db_size + second_co_size; + + p.cargo(&format!("clean gc --max-git-size={threshold} -Zgc -v")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(&format!( + "\ +[REMOVING] [ROOT]/home/.cargo/git/checkouts/bar-[HASH]/{first_co_name} +[REMOVED] [..] +" + )) + .run(); + + // And then try cleaning everything. + p.cargo("clean gc --max-git-size=0 -Zgc -v") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data( + format!( + "\ +[REMOVING] [ROOT]/home/.cargo/git/checkouts/bar-[HASH]/{second_co_name} +[REMOVING] [ROOT]/home/.cargo/git/db/bar-[HASH] +[REMOVED] [..] +" + ) + .unordered(), + ) + .run(); +} + +// Helper for setting up fake git sizes for git size cleaning. +fn setup_fake_git_sizes(db_name: &str, db_size: usize, co_sizes: &[usize]) { + let base_git = paths::home().join(".cargo/git"); + let db_path = base_git.join("db").join(db_name); + db_path.mkdir_p(); + std::fs::write(db_path.join("test"), "x".repeat(db_size)).unwrap(); + let base_co = base_git.join("checkouts").join(db_name); + for (i, size) in co_sizes.iter().enumerate() { + let co_name = format!("co{i}"); + let co_path = base_co.join(co_name); + co_path.mkdir_p(); + std::fs::write(co_path.join("test"), "x".repeat(*size)).unwrap(); + } +} + +#[cargo_test] +fn clean_max_git_size_untracked() { + // If there are git directories that aren't tracked in the database, + // `--max-git-size` should pick it up. + // + // The db_name of "example" depends on the sorting order of the names ("e" + // should be after "c"), so that the db comes after the checkouts. + setup_fake_git_sizes("example", 5000, &[1000, 2000]); + cargo_process(&format!("clean gc -Zgc -v --max-git-size=7000")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/checkouts/example/co0 +[REMOVED] 1 file, [FILE_SIZE]B total + +"#]]) + .run(); + cargo_process(&format!("clean gc -Zgc -v --max-git-size=5000")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/checkouts/example/co1 +[REMOVED] 1 file, [FILE_SIZE]B total + +"#]]) + .run(); + cargo_process(&format!("clean gc -Zgc -v --max-git-size=0")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/db/example +[REMOVED] 1 file, [FILE_SIZE]B total + +"#]]) + .run(); +} + +#[cargo_test] +fn clean_max_git_size_deletes_co_from_db() { + // In the scenario where it thinks it needs to delete the db, it should + // also delete all the checkouts. + // + // The db_name of "abc" depends on the sorting order of the names ("a" + // should be before "c"), so that the db comes before the checkouts. + setup_fake_git_sizes("abc", 5000, &[1000, 2000]); + // This deletes everything because it tries to delete the db, which then + // deletes all checkouts. + cargo_process(&format!("clean gc -Zgc -v --max-git-size=3000")) + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/db/abc +[REMOVING] [ROOT]/home/.cargo/git/checkouts/abc/co1 +[REMOVING] [ROOT]/home/.cargo/git/checkouts/abc/co0 +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); +} + +#[cargo_test] +fn handles_missing_index() { + // Checks behavior when index is missing. + let p = basic_foo_bar_project(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + paths::home().join(".cargo/registry/index").rm_rf(); + cargo_process("clean gc -v --max-download-size=0 -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data( + str![[r#" +[REMOVING] [ROOT]/home/.cargo/registry/cache/-[HASH] +[REMOVING] [ROOT]/home/.cargo/registry/src/-[HASH] +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn handles_missing_git_db() { + // Checks behavior when git db is missing. + let git_project = git::new("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + paths::home().join(".cargo/git/db").rm_rf(); + cargo_process("clean gc -v --max-git-size=0 -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/git/checkouts/bar-[HASH] +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); +} + +#[cargo_test] +fn clean_gc_quiet_is_quiet() { + // Checks that --quiet works with `cargo clean gc`, since there was a + // subtle issue with how the flag is defined as a global flag. + let p = basic_foo_bar_project(); + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + p.cargo("clean gc --quiet -Zgc --dry-run") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stdout_data("") + .with_stderr_data("") + .run(); + // Verify exact same command without -q would actually display something. + p.cargo("clean gc -Zgc --dry-run") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[SUMMARY] [FILE_NUM] files, [FILE_SIZE]B total +[WARNING] no files deleted due to --dry-run + +"#]]) + .run(); +} + +#[cargo_test(requires_rustup_stable)] +fn compatible_with_older_cargo() { + // Ensures that db stays backwards compatible across versions. + + // T-4 months: Current version, build the database. + Package::new("old", "1.0.0").publish(); + Package::new("middle", "1.0.0").publish(); + Package::new("new", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + old = "1.0" + middle = "1.0" + new = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + // Populate the last-use data. + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + assert_eq!( + get_registry_names("src"), + ["middle-1.0.0", "new-1.0.0", "old-1.0.0"] + ); + assert_eq!( + get_registry_names("cache"), + ["middle-1.0.0.crate", "new-1.0.0.crate", "old-1.0.0.crate"] + ); + + // T-2 months: Stable version, make sure it reads and deletes old src. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + new = "1.0" + middle = "1.0" + "#, + ); + rustup_cargo() + .args(&["+stable", "check", "-Zgc"]) + .cwd(p.root()) + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(2)) + .run(); + assert_eq!(get_registry_names("src"), ["middle-1.0.0", "new-1.0.0"]); + assert_eq!( + get_registry_names("cache"), + ["middle-1.0.0.crate", "new-1.0.0.crate", "old-1.0.0.crate"] + ); + + // T-0 months: Current version, make sure it can read data from stable, + // deletes old crate and middle src. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + new = "1.0" + "#, + ); + p.cargo("check -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + assert_eq!(get_registry_names("src"), ["new-1.0.0"]); + assert_eq!( + get_registry_names("cache"), + ["middle-1.0.0.crate", "new-1.0.0.crate"] + ); +} + +#[cargo_test(requires_rustup_stable)] +fn forward_compatible() { + // Checks that db created in an older version can be read in a newer version. + Package::new("bar", "1.0.0").publish(); + let git_project = git::new("from_git", |p| { + p.file("Cargo.toml", &basic_manifest("from_git", "1.0.0")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + + [dependencies] + bar = "1.0.0" + from_git = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + rustup_cargo() + .args(&["+stable", "check", "-Zgc"]) + .cwd(p.root()) + .masquerade_as_nightly_cargo(&["gc"]) + .run(); + + let config = GlobalContextBuilder::new().build(); + let lock = config + .acquire_package_cache_lock(CacheLockMode::MutateExclusive) + .unwrap(); + let tracker = GlobalCacheTracker::new(&config).unwrap(); + // Don't want to check the actual index name here, since although the + // names are semi-stable, they might change over long periods of time. + let indexes = tracker.registry_index_all().unwrap(); + assert_eq!(indexes.len(), 1); + let crates = tracker.registry_crate_all().unwrap(); + let names: Vec<_> = crates + .iter() + .map(|(krate, _timestamp)| krate.crate_filename) + .collect(); + assert_eq!(names, &["bar-1.0.0.crate"]); + let srcs = tracker.registry_src_all().unwrap(); + let names: Vec<_> = srcs + .iter() + .map(|(src, _timestamp)| src.package_dir) + .collect(); + assert_eq!(names, &["bar-1.0.0"]); + let dbs: Vec<_> = tracker.git_db_all().unwrap(); + assert_eq!(dbs.len(), 1); + let cos: Vec<_> = tracker.git_checkout_all().unwrap(); + assert_eq!(cos.len(), 1); + drop(lock); +} + +#[cargo_test] +fn resilient_to_unexpected_files() { + // Tests that it doesn't choke on unexpected files. + Package::new("bar", "1.0.0").publish(); + let git_project = git::new("from_git", |p| { + p.file("Cargo.toml", &basic_manifest("from_git", "1.0.0")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + + [dependencies] + bar = "1.0.0" + from_git = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .env("__CARGO_TEST_LAST_USE_NOW", months_ago_unix(4)) + .run(); + + let root = paths::home().join(".cargo"); + std::fs::write(root.join("registry/index/foo"), "").unwrap(); + std::fs::write(root.join("registry/cache/foo"), "").unwrap(); + std::fs::write(root.join("registry/src/foo"), "").unwrap(); + std::fs::write(root.join("git/db/foo"), "").unwrap(); + std::fs::write(root.join("git/checkouts/foo"), "").unwrap(); + + p.cargo("clean gc -Zgc") + .masquerade_as_nightly_cargo(&["gc"]) + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/help.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/help.rs new file mode 100644 index 000000000..0ba497e41 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/help.rs @@ -0,0 +1,159 @@ +//! Tests for cargo's help output. + +use std::fs; +use std::path::Path; +use std::str::from_utf8; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, cargo_process, paths, project}; + +#[cargo_test] +fn help() { + cargo_process("").run(); + cargo_process("help").run(); + cargo_process("-h").run(); + cargo_process("help build").run(); + cargo_process("build -h").run(); + cargo_process("help help").run(); +} + +#[cargo_test] +fn help_external_subcommand() { + // Check that `help external-subcommand` forwards the --help flag to the + // given subcommand. + Package::new("cargo-fake-help", "1.0.0") + .file( + "src/main.rs", + r#" + fn main() { + if ::std::env::args().nth(2) == Some(String::from("--help")) { + println!("fancy help output"); + } + } + "#, + ) + .publish(); + cargo_process("install cargo-fake-help").run(); + cargo_process("help fake-help") + .with_stdout_data(str![[r#" +fancy help output + +"#]]) + .run(); +} + +fn help_with_man(display_command: &str) { + // Build a "man" process that just echoes the contents. + let p = project() + .at(display_command) + .file("Cargo.toml", &basic_manifest(display_command, "1.0.0")) + .file( + "src/main.rs", + &r#" + fn main() { + eprintln!("custom __COMMAND__"); + let path = std::env::args().skip(1).next().unwrap(); + let mut f = std::fs::File::open(path).unwrap(); + std::io::copy(&mut f, &mut std::io::stdout()).unwrap(); + } + "# + .replace("__COMMAND__", display_command), + ) + .build(); + p.cargo("build").run(); + + help_with_man_and_path(display_command, "build", "build", &p.target_debug_dir()); +} + +fn help_with_man_and_path( + display_command: &str, + subcommand: &str, + actual_subcommand: &str, + path: &Path, +) { + let contents = if display_command == "man" { + fs::read_to_string(format!("src/etc/man/cargo-{}.1", actual_subcommand)).unwrap() + } else { + fs::read_to_string(format!( + "src/doc/man/generated_txt/cargo-{}.txt", + actual_subcommand + )) + .unwrap() + }; + + let output = cargo_process(&format!("help {subcommand}")) + .env("PATH", path) + .run(); + let stderr = from_utf8(&output.stderr).unwrap(); + if display_command.is_empty() { + assert_eq!(stderr, ""); + } else { + assert_eq!(stderr, format!("custom {}\n", display_command)); + } + let stdout = from_utf8(&output.stdout).unwrap(); + assert_eq!(stdout, contents); +} + +fn help_with_stdout_and_path(subcommand: &str, path: &Path) -> String { + let output = cargo_process(&format!("help {subcommand}")) + .env("PATH", path) + .run(); + let stderr = from_utf8(&output.stderr).unwrap(); + assert_eq!(stderr, ""); + let stdout = from_utf8(&output.stdout).unwrap(); + stdout.to_string() +} + +#[cargo_test] +fn help_man() { + // Checks that `help command` displays the man page using the given command. + help_with_man("man"); + help_with_man("less"); + help_with_man("more"); + + // Check with no commands in PATH. + help_with_man_and_path("", "build", "build", Path::new("")); +} + +#[cargo_test] +fn help_alias() { + // Check that `help some_alias` will resolve. + help_with_man_and_path("", "b", "build", Path::new("")); + + let config = paths::root().join(".cargo/config.toml"); + fs::create_dir_all(config.parent().unwrap()).unwrap(); + fs::write( + config, + r#" + [alias] + empty-alias = "" + simple-alias = "build" + complex-alias = ["build", "--release"] + "#, + ) + .unwrap(); + + // The `empty-alias` returns an error. + cargo_process("help empty-alias") + .env("PATH", Path::new("")) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such command: `empty-alias` + +[HELP] a command with a similar name exists: `empty-alias` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `empty-alias` with `cargo search cargo-empty-alias` + +"#]]) + .run(); + + // Because `simple-alias` aliases a subcommand with no arguments, help shows the manpage. + help_with_man_and_path("", "simple-alias", "build", Path::new("")); + + // Help for `complex-alias` displays the full alias command. + let out = help_with_stdout_and_path("complex-alias", Path::new("")); + assert_eq!(out, "`complex-alias` is aliased to `build --release`\n"); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/https.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/https.rs new file mode 100644 index 000000000..d81a51ee4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/https.rs @@ -0,0 +1,165 @@ +//! Network tests for https transport. +//! +//! Note that these tests will generally require setting `CARGO_CONTAINER_TESTS` +//! or `CARGO_PUBLIC_NETWORK_TESTS`. + +use cargo_test_support::containers::Container; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test(container_test)] +fn self_signed_should_fail() { + // Cargo should not allow a connection to a self-signed certificate. + let apache = Container::new("apache").launch(); + let port = apache.port_mappings[&443]; + let url = format!("https://127.0.0.1:{port}/repos/bar.git"); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = "{url}" }} + "# + ), + ) + .file("src/lib.rs", "") + .build(); + // I think the text here depends on the curl backend. + let err_msg = if cfg!(target_os = "macos") { + "untrusted connection error; class=Ssl (16)[..]" + } else if cfg!(unix) { + "the SSL certificate is invalid; class=Ssl (16)[..]" + } else if cfg!(windows) { + "user cancelled certificate check; class=Http (34); code=Certificate (-17)" + } else { + panic!("target not supported"); + }; + p.cargo("fetch") + .with_status(101) + .with_stderr_data(&format!( + "\ +[UPDATING] git repository `https://127.0.0.1:[..]/repos/bar.git` +[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update https://127.0.0.1:[..]/repos/bar.git + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: + network failure seems to have happened + if a proxy or similar is necessary `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: + {err_msg} +" + )) + .run(); +} + +#[cargo_test(container_test)] +fn self_signed_with_cacert() { + // When using cainfo, that should allow a connection to a self-signed cert. + + if cfg!(target_os = "macos") { + // This test only seems to work with the + // curl-sys/force-system-lib-on-osx feature enabled. For some reason + // SecureTransport doesn't seem to like the self-signed certificate. + // It works if the certificate is manually approved via Keychain + // Access. The system libcurl is built with a LibreSSL fallback which + // is used when CAINFO is set, which seems to work correctly. This + // could use some more investigation. The official Rust binaries use + // curl-sys/force-system-lib-on-osx so it is mostly an issue for local + // testing. + // + // The error is: + // [60] SSL peer certificate or SSH remote key was not OK (SSL: + // certificate verification failed (result: 5)); class=Net (12) + let curl_v = curl::Version::get(); + if curl_v.vendored() { + eprintln!( + "vendored curl not supported on macOS, \ + set curl-sys/force-system-lib-on-osx to enable" + ); + return; + } + } + + let apache = Container::new("apache").launch(); + let port = apache.port_mappings[&443]; + let url = format!("https://127.0.0.1:{port}/repos/bar.git"); + let server_crt = apache.read_file("/usr/local/apache2/conf/server.crt"); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = "{url}" }} + "# + ), + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [http] + cainfo = "server.crt" + "# + ), + ) + .file("server.crt", &server_crt) + .build(); + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] git repository `https://127.0.0.1:[..]/repos/bar.git` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); +} + +#[cargo_test(public_network_test)] +fn github_works() { + // Check that an https connection to github.com works. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bitflags = { git = "https://github.com/rust-lang/bitflags.git", tag="1.3.2" } + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] git repository `https://github.com/rust-lang/bitflags.git` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/inheritable_workspace_fields.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/inheritable_workspace_fields.rs new file mode 100644 index 000000000..14e02aa83 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/inheritable_workspace_fields.rs @@ -0,0 +1,1920 @@ +//! Tests for inheriting Cargo.toml fields with field.workspace = true + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package, RegistryBuilder}; +use cargo_test_support::{ + basic_lib_manifest, basic_manifest, git, paths, project, publish, registry, str, +}; + +#[cargo_test] +fn permit_additional_workspace_fields() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [workspace.package] + version = "1.2.3" + authors = ["Rustaceans"] + description = "This is a crate" + documentation = "https://www.rust-lang.org/learn" + readme = "README.md" + homepage = "https://www.rust-lang.org" + repository = "https://github.com/example/example" + license = "MIT" + license-file = "LICENSE" + keywords = ["cli"] + categories = ["development-tools"] + publish = false + edition = "2018" + rust-version = "1.60" + exclude = ["foo.txt"] + include = ["bar.txt", "**/*.rs", "Cargo.toml", "LICENSE", "README.md"] + + [workspace.dependencies] + dep = "0.1" + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + // Should not warn about unused fields. + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check").run(); + let lockfile = p.read_lockfile(); + assert!(!lockfile.contains("dep")); +} + +#[cargo_test] +fn deny_optional_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + + [workspace.dependencies] + dep1 = { version = "0.1", optional = true } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dep1 is optional, but workspace dependencies cannot be optional + +"#]]) + .run(); +} + +#[cargo_test] +fn inherit_own_workspace_fields() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version.workspace = true + authors.workspace = true + description.workspace = true + documentation.workspace = true + homepage.workspace = true + repository.workspace = true + license.workspace = true + keywords.workspace = true + categories.workspace = true + publish.workspace = true + edition.workspace = true + rust-version.workspace = true + exclude.workspace = true + include.workspace = true + + [workspace] + members = [] + [workspace.package] + version = "1.2.3" + authors = ["Rustaceans"] + description = "This is a crate" + documentation = "https://www.rust-lang.org/learn" + homepage = "https://www.rust-lang.org" + repository = "https://github.com/example/example" + license = "MIT" + keywords = ["cli"] + categories = ["development-tools"] + publish = true + edition = "2018" + rust-version = "1.60" + exclude = ["foo.txt"] + include = ["bar.txt", "**/*.rs", "Cargo.toml"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("foo.txt", "") // should be ignored when packaging + .file("bar.txt", "") // should be included when packaging + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] both package.include and package.exclude are specified; the exclude list will be ignored +[PACKAGING] foo v1.2.3 ([ROOT]/foo) +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v1.2.3 ([ROOT]/foo) +[COMPILING] foo v1.2.3 ([ROOT]/foo/target/package/foo-1.2.3) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v1.2.3 ([ROOT]/foo) +[UPLOADED] foo v1.2.3 to registry `crates-io` +[NOTE] waiting for `foo v1.2.3` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v1.2.3 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": ["Rustaceans"], + "badges": {}, + "categories": ["development-tools"], + "deps": [], + "description": "This is a crate", + "documentation": "https://www.rust-lang.org/learn", + "features": {}, + "homepage": "https://www.rust-lang.org", + "keywords": ["cli"], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": "https://github.com/example/example", + "rust_version": "1.60", + "vers": "1.2.3" + } + "#, + "foo-1.2.3.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + ".cargo_vcs_info.json", + "bar.txt", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.60" +name = "foo" +version = "1.2.3" +authors = ["Rustaceans"] +build = false +exclude = ["foo.txt"] +include = [ + "bar.txt", + "**/*.rs", + "Cargo.toml", +] +publish = true +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "This is a crate" +homepage = "https://www.rust-lang.org" +documentation = "https://www.rust-lang.org/learn" +readme = false +keywords = ["cli"] +categories = ["development-tools"] +license = "MIT" +repository = "https://github.com/example/example" + +[[bin]] +name = "foo" +path = "src/main.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn inherit_own_dependencies() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + + [dependencies] + dep.workspace = true + + [build-dependencies] + dep-build.workspace = true + + [dev-dependencies] + dep-dev.workspace = true + + [workspace] + members = [] + + [workspace.dependencies] + dep = "0.1" + dep-build = "0.8" + dep-dev = "0.5.2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("dep", "0.1.2").publish(); + Package::new("dep-build", "0.8.2").publish(); + Package::new("dep-dev", "0.5.2").publish(); + + p.cargo("check") + // Unordered because the download order is nondeterministic. + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) +[DOWNLOADED] dep-build v0.8.2 (registry `dummy-registry`) +[CHECKING] dep v0.1.2 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + p.cargo("check").run(); + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("dep")); + assert!(lockfile.contains("dep-dev")); + assert!(lockfile.contains("dep-build")); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] bar v0.2.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.2.0 ([ROOT]/foo) +[COMPILING] dep v0.1.2 +[COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] bar v0.2.0 ([ROOT]/foo) +[UPLOADED] bar v0.2.0 to registry `crates-io` +[NOTE] waiting for `bar v0.2.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v0.2.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "dep", + "optional": false, + "target": null, + "version_req": "^0.1" + }, + { + "default_features": true, + "features": [], + "kind": "dev", + "name": "dep-dev", + "optional": false, + "target": null, + "version_req": "^0.5.2" + }, + { + "default_features": true, + "features": [], + "kind": "build", + "name": "dep-build", + "optional": false, + "target": null, + "version_req": "^0.8" + } + ], + "description": null, + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "name": "bar", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.2.0" + } + "#, + "bar-0.2.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "bar" +version = "0.2.0" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false + +[[bin]] +name = "bar" +path = "src/main.rs" + +[dependencies.dep] +version = "0.1" + +[dev-dependencies.dep-dev] +version = "0.5.2" + +[build-dependencies.dep-build] +version = "0.8" + +"##]], + )], + ); +} + +#[cargo_test] +fn inherit_own_detailed_dependencies() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + + [dependencies] + dep.workspace = true + + [workspace] + members = [] + + [workspace.dependencies] + dep = { version = "0.1.2", features = ["testing"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("dep", "0.1.2") + .feature("testing", &vec![]) + .publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) +[CHECKING] dep v0.1.2 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check").run(); + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("dep")); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] bar v0.2.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.2.0 ([ROOT]/foo) +[COMPILING] dep v0.1.2 +[COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] bar v0.2.0 ([ROOT]/foo) +[UPLOADED] bar v0.2.0 to registry `crates-io` +[NOTE] waiting for `bar v0.2.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v0.2.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": ["testing"], + "kind": "normal", + "name": "dep", + "optional": false, + "target": null, + "version_req": "^0.1.2" + } + ], + "description": null, + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "name": "bar", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.2.0" + } + "#, + "bar-0.2.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "bar" +version = "0.2.0" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false + +[[bin]] +name = "bar" +path = "src/main.rs" + +[dependencies.dep] +version = "0.1.2" +features = ["testing"] + +"##]], + )], + ); +} + +#[cargo_test] +fn inherit_from_own_undefined_field() { + registry::init(); + + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.2.5" + edition = "2015" + authors = ["rustaceans"] + description.workspace = true + + [workspace] + members = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + error inheriting `description` from workspace root manifest's `workspace.package.description` + +Caused by: + `workspace.package.description` was not defined + +"#]]) + .run(); +} + +#[cargo_test] +fn inherited_dependencies_union_features() { + Package::new("dep", "0.1.0") + .feature("fancy", &["fancy_dep"]) + .feature("dancy", &["dancy_dep"]) + .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) + .add_dep(Dependency::new("dancy_dep", "0.6").optional(true)) + .file("src/lib.rs", "") + .publish(); + + Package::new("fancy_dep", "0.2.4").publish(); + Package::new("dancy_dep", "0.6.8").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep = { workspace = true, features = ["dancy"] } + + [workspace] + members = [] + [workspace.dependencies] + dep = { version = "0.1", features = ["fancy"] } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[DOWNLOADED] dancy_dep v0.6.8 (registry `dummy-registry`) +[CHECKING] fancy_dep v0.2.4 +[CHECKING] dancy_dep v0.6.8 +[CHECKING] dep v0.1.0 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("dep")); + assert!(lockfile.contains("fancy_dep")); + assert!(lockfile.contains("dancy_dep")); +} + +#[cargo_test] +fn inherit_workspace_fields() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [workspace.package] + version = "1.2.3" + authors = ["Rustaceans"] + description = "This is a crate" + documentation = "https://www.rust-lang.org/learn" + readme = "README.md" + homepage = "https://www.rust-lang.org" + repository = "https://github.com/example/example" + license = "MIT" + license-file = "LICENSE" + keywords = ["cli"] + categories = ["development-tools"] + publish = true + edition = "2018" + rust-version = "1.60" + exclude = ["foo.txt"] + include = ["bar.txt", "**/*.rs", "Cargo.toml", "LICENSE", "README.md"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + workspace = ".." + version.workspace = true + authors.workspace = true + description.workspace = true + documentation.workspace = true + readme.workspace = true + homepage.workspace = true + repository.workspace = true + license.workspace = true + license-file.workspace = true + keywords.workspace = true + categories.workspace = true + publish.workspace = true + edition.workspace = true + rust-version.workspace = true + exclude.workspace = true + include.workspace = true + "#, + ) + .file("LICENSE", "license") + .file("README.md", "README.md") + .file("bar/src/main.rs", "fn main() {}") + .file("bar/foo.txt", "") // should be ignored when packaging + .file("bar/bar.txt", "") // should be included when packaging + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .cwd("bar") + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] both package.include and package.exclude are specified; the exclude list will be ignored +[PACKAGING] bar v1.2.3 ([ROOT]/foo/bar) +[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v1.2.3 ([ROOT]/foo/bar) +[WARNING] only one of `license` or `license-file` is necessary +`license` should be used if the package license can be expressed with a standard SPDX expression. +`license-file` should be used if the package uses a non-standard license. +See https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields for more information. +[COMPILING] bar v1.2.3 ([ROOT]/foo/target/package/bar-1.2.3) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] bar v1.2.3 ([ROOT]/foo/bar) +[UPLOADED] bar v1.2.3 to registry `crates-io` +[NOTE] waiting for `bar v1.2.3` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v1.2.3 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": ["Rustaceans"], + "badges": {}, + "categories": ["development-tools"], + "deps": [], + "description": "This is a crate", + "documentation": "https://www.rust-lang.org/learn", + "features": {}, + "homepage": "https://www.rust-lang.org", + "keywords": ["cli"], + "license": "MIT", + "license_file": "LICENSE", + "links": null, + "name": "bar", + "readme": "README.md", + "readme_file": "README.md", + "repository": "https://github.com/example/example", + "rust_version": "1.60", + "vers": "1.2.3" + } + "#, + "bar-1.2.3.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + "README.md", + "LICENSE", + ".cargo_vcs_info.json", + "bar.txt", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.60" +name = "bar" +version = "1.2.3" +authors = ["Rustaceans"] +build = false +exclude = ["foo.txt"] +include = [ + "bar.txt", + "**/*.rs", + "Cargo.toml", + "LICENSE", + "README.md", +] +publish = true +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "This is a crate" +homepage = "https://www.rust-lang.org" +documentation = "https://www.rust-lang.org/learn" +readme = "README.md" +keywords = ["cli"] +categories = ["development-tools"] +license = "MIT" +license-file = "LICENSE" +repository = "https://github.com/example/example" + +[[bin]] +name = "bar" +path = "src/main.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn inherit_dependencies() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [workspace.dependencies] + dep = "0.1" + dep-build = "0.8" + dep-dev = "0.5.2" + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + workspace = ".." + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep.workspace = true + [build-dependencies] + dep-build.workspace = true + [dev-dependencies] + dep-dev.workspace = true + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + Package::new("dep", "0.1.2").publish(); + Package::new("dep-build", "0.8.2").publish(); + Package::new("dep-dev", "0.5.2").publish(); + + p.cargo("check") + // Unordered because the download order is nondeterministic. + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) +[DOWNLOADED] dep-build v0.8.2 (registry `dummy-registry`) +[CHECKING] dep v0.1.2 +[CHECKING] bar v0.2.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + p.cargo("check").run(); + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("dep")); + assert!(lockfile.contains("dep-dev")); + assert!(lockfile.contains("dep-build")); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .cwd("bar") + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] bar v0.2.0 ([ROOT]/foo/bar) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.2.0 ([ROOT]/foo/bar) +[COMPILING] dep v0.1.2 +[COMPILING] bar v0.2.0 ([ROOT]/foo/target/package/bar-0.2.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] bar v0.2.0 ([ROOT]/foo/bar) +[UPLOADED] bar v0.2.0 to registry `crates-io` +[NOTE] waiting for `bar v0.2.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] bar v0.2.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "dep", + "optional": false, + "target": null, + "version_req": "^0.1" + }, + { + "default_features": true, + "features": [], + "kind": "dev", + "name": "dep-dev", + "optional": false, + "target": null, + "version_req": "^0.5.2" + }, + { + "default_features": true, + "features": [], + "kind": "build", + "name": "dep-build", + "optional": false, + "target": null, + "version_req": "^0.8" + } + ], + "description": null, + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "name": "bar", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.2.0" + } + "#, + "bar-0.2.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "bar" +version = "0.2.0" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false + +[[bin]] +name = "bar" +path = "src/main.rs" + +[dependencies.dep] +version = "0.1" + +[dev-dependencies.dep-dev] +version = "0.5.2" + +[build-dependencies.dep-build] +version = "0.8" + +"##]], + )], + ); +} + +#[cargo_test] +fn inherit_target_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [workspace.dependencies] + dep = "0.1" + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + workspace = ".." + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [target.'cfg(unix)'.dependencies] + dep.workspace = true + [target.'cfg(windows)'.dependencies] + dep.workspace = true + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + Package::new("dep", "0.1.2").publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.2 (registry `dummy-registry`) +[CHECKING] dep v0.1.2 +[CHECKING] bar v0.2.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("dep")); +} + +#[cargo_test] +fn inherit_dependency_override_optional() { + Package::new("dep", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [workspace.dependencies] + dep = "0.1.0" + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + workspace = ".." + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep = { workspace = true, optional = true } + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.2.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn inherit_dependency_features() { + Package::new("dep", "0.1.0") + .feature("fancy", &["fancy_dep"]) + .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) + .file("src/lib.rs", "") + .publish(); + + Package::new("fancy_dep", "0.2.4").publish(); + Package::new("dancy_dep", "0.6.8").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep = { workspace = true, features = ["fancy"] } + + [workspace] + members = [] + [workspace.dependencies] + dep = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[CHECKING] fancy_dep v0.2.4 +[CHECKING] dep v0.1.0 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("dep")); + assert!(lockfile.contains("fancy_dep")); +} + +#[cargo_test] +fn inherit_detailed_dependencies() { + let git_project = git::new("detailed", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("detailed")) + .file( + "src/detailed.rs", + r#" + pub fn hello() -> &'static str { + "hello world" + } + "#, + ) + }); + + // Make a new branch based on the current HEAD commit + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let head = repo.head().unwrap().target().unwrap(); + let head = repo.find_commit(head).unwrap(); + repo.branch("branchy", &head, true).unwrap(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [workspace] + members = ["bar"] + [workspace.dependencies] + detailed = {{ git = '{}', branch = "branchy" }} + "#, + git_project.url() + ), + ) + .file( + "bar/Cargo.toml", + r#" + [package] + workspace = ".." + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + detailed.workspace = true + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/detailed` +[LOCKING] 1 package to latest compatible version +[CHECKING] detailed v0.5.0 ([ROOTURL]/detailed?branch=branchy#[..]) +[CHECKING] bar v0.2.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn inherit_path_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [workspace.dependencies] + dep = { path = "dep" } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + workspace = ".." + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep.workspace = true + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file("dep/Cargo.toml", &basic_manifest("dep", "0.9.0")) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] dep v0.9.0 ([ROOT]/foo/dep) +[CHECKING] bar v0.2.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("dep")); +} + +#[cargo_test] +fn error_workspace_false() { + registry::init(); + + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + workspace = ".." + version = "1.2.3" + edition = "2015" + authors = ["rustaceans"] + description = { workspace = false } + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .cwd("bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `workspace` cannot be false + --> Cargo.toml:8:41 + | +8 | description = { workspace = false } + | ^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn error_workspace_dependency_looked_for_workspace_itself() { + registry::init(); + + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "1.2.3" + edition = "2015" + + [dependencies] + dep.workspace = true + + [workspace] + members = [] + + [workspace.dependencies] + dep.workspace = true + + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dependency (dep) specified without providing a local path, Git repository, version, or workspace dependency to use + +"#]]) + .run(); +} + +#[cargo_test] +fn error_malformed_workspace_root() { + registry::init(); + + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [workspace] + members = [invalid toml + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + workspace = ".." + version = "1.2.3" + edition = "2015" + authors = ["rustaceans"] + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .cwd("bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid array +expected `]` + --> ../Cargo.toml:3:24 + | +3 | members = [invalid toml + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn error_no_root_workspace() { + registry::init(); + + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + workspace = ".." + version = "1.2.3" + edition = "2015" + authors = ["rustaceans"] + description.workspace = true + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .cwd("bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/bar/Cargo.toml` + +Caused by: + error inheriting `description` from workspace root manifest's `workspace.package.description` + +Caused by: + root of a workspace inferred but wasn't a root: [ROOT]/foo/Cargo.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn error_inherit_unspecified_dependency() { + let p = project().build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + workspace = ".." + version = "1.2.3" + edition = "2015" + authors = ["rustaceans"] + [dependencies] + foo.workspace = true + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .cwd("bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/bar/Cargo.toml` + +Caused by: + error inheriting `foo` from workspace root manifest's `workspace.dependencies.foo` + +Caused by: + `workspace.dependencies` was not defined + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_inherit_def_feat_true_member_def_feat_false() { + Package::new("dep", "0.1.0") + .feature("default", &["fancy_dep"]) + .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) + .file("src/lib.rs", "") + .publish(); + + Package::new("fancy_dep", "0.2.4").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep = { workspace = true, default-features = false } + + [workspace] + members = [] + [workspace.dependencies] + dep = { version = "0.1.0", default-features = true } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: `default-features` is ignored for dep, since `default-features` was true for `workspace.dependencies.dep`, this could become a hard error in the future +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[CHECKING] fancy_dep v0.2.4 +[CHECKING] dep v0.1.0 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn warn_inherit_def_feat_true_member_def_feat_false_2024_edition() { + Package::new("dep", "0.1.0") + .feature("default", &["fancy_dep"]) + .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) + .file("src/lib.rs", "") + .publish(); + + Package::new("fancy_dep", "0.2.4").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2024" + authors = [] + [dependencies] + dep = { workspace = true, default-features = false } + + [workspace] + members = [] + [workspace.dependencies] + dep = { version = "0.1.0", default-features = true } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + error inheriting `dep` from workspace root manifest's `workspace.dependencies.dep` + +Caused by: + `default-features = false` cannot override workspace's `default-features` + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_inherit_simple_member_def_feat_false() { + Package::new("dep", "0.1.0") + .feature("default", &["fancy_dep"]) + .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) + .file("src/lib.rs", "") + .publish(); + + Package::new("fancy_dep", "0.2.4").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep = { workspace = true, default-features = false } + + [workspace] + members = [] + [workspace.dependencies] + dep = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: `default-features` is ignored for dep, since `default-features` was not specified for `workspace.dependencies.dep`, this could become a hard error in the future +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[CHECKING] fancy_dep v0.2.4 +[CHECKING] dep v0.1.0 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn warn_inherit_simple_member_def_feat_false_2024_edition() { + Package::new("dep", "0.1.0") + .feature("default", &["fancy_dep"]) + .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) + .file("src/lib.rs", "") + .publish(); + + Package::new("fancy_dep", "0.2.4").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2024" + authors = [] + [dependencies] + dep = { workspace = true, default-features = false } + + [workspace] + members = [] + [workspace.dependencies] + dep = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + error inheriting `dep` from workspace root manifest's `workspace.dependencies.dep` + +Caused by: + `default-features = false` cannot override workspace's `default-features` + +"#]]) + .run(); +} + +#[cargo_test] +fn inherit_def_feat_false_member_def_feat_true() { + Package::new("dep", "0.1.0") + .feature("default", &["fancy_dep"]) + .add_dep(Dependency::new("fancy_dep", "0.2").optional(true)) + .file("src/lib.rs", "") + .publish(); + + Package::new("fancy_dep", "0.2.4").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + [dependencies] + dep = { workspace = true, default-features = true } + + [workspace] + members = [] + [workspace.dependencies] + dep = { version = "0.1.0", default-features = false } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] fancy_dep v0.2.4 (registry `dummy-registry`) +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[CHECKING] fancy_dep v0.2.4 +[CHECKING] dep v0.1.0 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cannot_inherit_in_patch() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [] + + [workspace.dependencies] + bar = { path = "bar" } + + [package] + name = "foo" + version = "0.2.0" + edition = "2015" + + [patch.crates-io] + bar.workspace = true + + [dependencies] + bar = "0.1.0" + + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dependency (bar) specified without providing a local path, Git repository, version, or workspace dependency to use + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_inherit_unused_manifest_key_dep() { + Package::new("dep", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [] + [workspace.dependencies] + dep = { version = "0.1", wxz = "wxz" } + + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + authors = [] + + [dependencies] + dep = { workspace = true, wxz = "wxz" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.dependencies.dep.wxz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: dependencies.dep.wxz +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[CHECKING] dep v0.1.0 +[CHECKING] bar v0.2.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_unused_workspace_package_field() { + Package::new("dep", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [] + [workspace.package] + name = "unused" + + [package] + name = "foo" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: workspace.package.name +[CHECKING] foo v0.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_inherit_unused_manifest_key_package() { + Package::new("dep", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [] + [workspace.package] + version = "1.2.3" + authors = ["Rustaceans"] + description = "This is a crate" + documentation = "https://www.rust-lang.org/learn" + homepage = "https://www.rust-lang.org" + repository = "https://github.com/example/example" + license = "MIT" + keywords = ["cli"] + categories = ["development-tools"] + publish = true + edition = "2018" + rust-version = "1.60" + exclude = ["foo.txt"] + include = ["bar.txt", "**/*.rs", "Cargo.toml"] + + [package] + name = "bar" + version = { workspace = true, xyz = "abc"} + authors = { workspace = true, xyz = "abc"} + description = { workspace = true, xyz = "abc"} + documentation = { workspace = true, xyz = "abc"} + homepage = { workspace = true, xyz = "abc"} + repository = { workspace = true, xyz = "abc"} + license = { workspace = true, xyz = "abc"} + keywords = { workspace = true, xyz = "abc"} + categories = { workspace = true, xyz = "abc"} + publish = { workspace = true, xyz = "abc"} + edition = { workspace = true, xyz = "abc"} + rust-version = { workspace = true, xyz = "abc"} + exclude = { workspace = true, xyz = "abc"} + include = { workspace = true, xyz = "abc"} + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.authors.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.categories.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.description.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.documentation.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.edition.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.exclude.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.homepage.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.include.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.keywords.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.license.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.publish.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.repository.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.rust-version.xyz +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: package.version.xyz +[CHECKING] bar v1.2.3 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install.rs new file mode 100644 index 000000000..714ef7e5b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install.rs @@ -0,0 +1,2887 @@ +//! Tests for the `cargo install` command. + +use std::env; +use std::fs::{self, OpenOptions}; +use std::io::prelude::*; +use std::path::Path; +use std::path::PathBuf; +use std::thread; + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::cross_compile; +use cargo_test_support::git; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package}; +use cargo_test_support::str; +use cargo_test_support::{ + basic_manifest, cargo_process, project, project_in, symlink_supported, t, +}; +use cargo_util::{ProcessBuilder, ProcessError}; + +use cargo_test_support::install::{assert_has_installed_exe, assert_has_not_installed_exe, exe}; +use cargo_test_support::paths; + +fn pkg(name: &str, vers: &str) { + Package::new(name, vers) + .file("src/lib.rs", "") + .file( + "src/main.rs", + &format!("extern crate {}; fn main() {{}}", name), + ) + .publish(); +} + +#[cargo_test] +fn simple() { + pkg("foo", "0.0.1"); + + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + + cargo_process("uninstall foo") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn install_the_same_version_twice() { + pkg("foo", "0.0.1"); + + cargo_process("install foo foo") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn toolchain() { + pkg("foo", "0.0.1"); + + cargo_process("install +nightly") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character `+` in package name: `+nightly` + Use `cargo +nightly install` if you meant to use the `nightly` toolchain. + +"#]]) + .run(); +} + +#[cargo_test] +fn url() { + pkg("foo", "0.0.1"); + cargo_process("install https://github.com/bar/foo") + .with_status(101) + .with_stderr_data(str![[r#" +[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"); + + cargo_process("install foo --message-format=json") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries + +"#]]) + .with_stdout_data( + str![[r#" +[ + { + "executable": null, + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/Cargo.toml", + "package_id": "registry+https://github.com/rust-lang/crates.io-index#foo@0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/src/lib.rs", + "test": true + } + }, + { + "executable": "[..]", + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/Cargo.toml", + "package_id": "registry+https://github.com/rust-lang/crates.io-index#foo@0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foo-0.0.1/src/main.rs", + "test": true + } + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn with_index() { + let registry = registry::init(); + pkg("foo", "0.0.1"); + + cargo_process("install foo --index") + .arg(registry.index_url().as_str()) + .with_stderr_data(str![[r#" +[UPDATING] `[ROOT]/registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `[ROOT]/registry`) +[INSTALLING] foo v0.0.1 (registry `[ROOT]/registry`) +[COMPILING] foo v0.0.1 (registry `[ROOT]/registry`) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1 (registry `[ROOT]/registry`)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + + cargo_process("uninstall foo") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn multiple_pkgs() { + pkg("foo", "0.0.1"); + pkg("bar", "0.0.2"); + + cargo_process("install foo bar baz") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`) +[ERROR] could not find `baz` in registry `crates-io` with version `*` +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[INSTALLING] bar v0.0.2 +[COMPILING] bar v0.0.2 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE] +[INSTALLED] package `bar v0.0.2` (executable `bar[EXE]`) +[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above). +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries +[ERROR] some crates failed to install + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_installed_exe(paths::cargo_home(), "bar"); + + cargo_process("uninstall foo bar") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] +[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE] +[SUMMARY] Successfully uninstalled foo, bar! + +"#]]) + .run(); + + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + assert_has_not_installed_exe(paths::cargo_home(), "bar"); +} + +fn path() -> Vec { + env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect() +} + +#[cargo_test] +fn multiple_pkgs_path_set() { + // confirm partial failure results in 101 status code and does not have the + // '[WARNING] be sure to add `[..]` to your PATH to be able to run the installed binaries' + // even if CARGO_HOME/bin is in the PATH + pkg("foo", "0.0.1"); + pkg("bar", "0.0.2"); + + // add CARGO_HOME/bin to path + let mut path = path(); + path.push(paths::cargo_home().join("bin")); + let new_path = env::join_paths(path).unwrap(); + cargo_process("install foo bar baz") + .env("PATH", new_path) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`) +[ERROR] could not find `baz` in registry `crates-io` with version `*` +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[INSTALLING] bar v0.0.2 +[COMPILING] bar v0.0.2 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE] +[INSTALLED] package `bar v0.0.2` (executable `bar[EXE]`) +[SUMMARY] Successfully installed foo, bar! Failed to install baz (see error(s) above). +[ERROR] some crates failed to install + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_installed_exe(paths::cargo_home(), "bar"); + + cargo_process("uninstall foo bar") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] +[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE] +[SUMMARY] Successfully uninstalled foo, bar! + +"#]]) + .run(); + + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + assert_has_not_installed_exe(paths::cargo_home(), "bar"); +} + +#[cargo_test] +fn pick_max_version() { + pkg("foo", "0.1.0"); + pkg("foo", "0.2.0"); + pkg("foo", "0.2.1"); + pkg("foo", "0.2.1-pre.1"); + pkg("foo", "0.3.0-pre.2"); + + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.2.1 (registry `dummy-registry`) +[INSTALLING] foo v0.2.1 +[COMPILING] foo v0.2.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.2.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn installs_beta_version_by_explicit_name_from_git() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.3.0-beta.1")) + .file("src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .arg("foo") + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn missing() { + pkg("foo", "0.0.1"); + cargo_process("install bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] could not find `bar` in registry `crates-io` with version `*` + +"#]]) + .run(); +} + +#[cargo_test] +fn missing_current_working_directory() { + cargo_process("install .") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] To install the binaries for the package in current working directory use `cargo install --path .`. +Use `cargo build` if you want to simply build the package. + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_version() { + pkg("foo", "0.0.1"); + cargo_process("install foo --version=0.2.0") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] could not find `foo` in registry `crates-io` with version `=0.2.0` + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_paths() { + cargo_process("install") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `[ROOT]` is not a crate root; specify a crate to install from crates.io, or use --path or --git to specify an alternate source + +"#]]) + .run(); + + cargo_process("install --path .") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `[ROOT]` does not contain a Cargo.toml file. --path must point to a directory containing a Cargo.toml file. + +"#]]) + .run(); + + let toml = paths::root().join("Cargo.toml"); + fs::write(toml, "").unwrap(); + cargo_process("install --path Cargo.toml") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `[ROOT]/Cargo.toml` is not a directory. --path must point to a directory containing a Cargo.toml file. + +"#]]) + .run(); + + cargo_process("install --path .") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/Cargo.toml` +... +"#]]) + .run(); +} + +#[cargo_test] +fn install_location_precedence() { + pkg("foo", "0.0.1"); + + let root = paths::root(); + let t1 = root.join("t1"); + let t2 = root.join("t2"); + let t3 = root.join("t3"); + let t4 = paths::cargo_home(); + + fs::create_dir(root.join(".cargo")).unwrap(); + fs::write( + root.join(".cargo/config.toml"), + &format!( + "[install] + root = '{}' + ", + t3.display() + ), + ) + .unwrap(); + + println!("install --root"); + + cargo_process("install foo --root") + .arg(&t1) + .env("CARGO_INSTALL_ROOT", &t2) + .run(); + assert_has_installed_exe(&t1, "foo"); + assert_has_not_installed_exe(&t2, "foo"); + + println!("install CARGO_INSTALL_ROOT"); + + cargo_process("install foo") + .env("CARGO_INSTALL_ROOT", &t2) + .run(); + assert_has_installed_exe(&t2, "foo"); + assert_has_not_installed_exe(&t3, "foo"); + + println!("install install.root"); + + cargo_process("install foo").run(); + assert_has_installed_exe(&t3, "foo"); + assert_has_not_installed_exe(&t4, "foo"); + + fs::remove_file(root.join(".cargo/config.toml")).unwrap(); + + println!("install cargo home"); + + cargo_process("install foo").run(); + assert_has_installed_exe(&t4, "foo"); +} + +#[cargo_test] +fn install_path() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + cargo_process("install --path").arg(p.root()).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + // path-style installs force a reinstall + p.cargo("install --path .").with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); +} + +#[cargo_test] +fn install_target_dir() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("install --target-dir td_test") + .with_stderr_data(str![[r#" +[WARNING] Using `cargo install` to install the binaries from the package in current working directory is deprecated, use `cargo install --path .` instead. Use `cargo build` if you want to simply build the package. +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + let mut path = p.root(); + path.push("td_test"); + assert!(path.exists()); + + #[cfg(not(windows))] + path.push("release/foo"); + #[cfg(windows)] + path.push("release/foo.exe"); + assert!(path.exists()); +} + +#[cargo_test] +#[cfg(target_os = "linux")] +fn install_path_with_lowercase_cargo_toml() { + let toml = paths::root().join("cargo.toml"); + fs::write(toml, "").unwrap(); + + cargo_process("install --path .") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `[ROOT]` does not contain a Cargo.toml file, but found cargo.toml please try to rename it to Cargo.toml. --path must point to a directory containing a Cargo.toml file. + +"#]] + ) + .run(); +} + +#[cargo_test] +fn install_relative_path_outside_current_ws() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [workspace] + members = ["baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + authors = [] + edition = "2021" + + [dependencies] + foo = "1" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + let _bin_project = project_in("bar") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("install --path ../bar/foo") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/bar/foo) +[COMPILING] foo v0.0.1 ([ROOT]/bar/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1 ([ROOT]/bar/foo)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + // Validate the workspace error message to display available targets. + p.cargo("install --path ../bar/foo --bin") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_packages_containing_binaries() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("a/src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/foo` +[ERROR] multiple packages with binaries found: bar, foo. When installing a git repository, cargo will always search the entire repo for any Cargo.toml. +Please specify a package, e.g. `cargo install --git [ROOTURL]/foo bar`. + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_packages_matching_example() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "") + .file("examples/ex1.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .file("bar/examples/ex1.rs", "fn main() {}") + .build(); + + cargo_process("install --example ex1 --git") + .arg(p.url().to_string()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/foo` +[ERROR] multiple packages with examples found: bar, foo. When installing a git repository, cargo will always search the entire repo for any Cargo.toml. +Please specify a package, e.g. `cargo install --git [ROOTURL]/foo bar`. + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_binaries_deep_select_uses_package_name() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("bar/baz/src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .arg("baz") + .run(); +} + +#[cargo_test] +fn multiple_binaries_in_selected_package_installs_all() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/bin/bin1.rs", "fn main() {}") + .file("bar/src/bin/bin2.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .arg("bar") + .run(); + + let cargo_home = paths::cargo_home(); + assert_has_installed_exe(&cargo_home, "bin1"); + assert_has_installed_exe(&cargo_home, "bin2"); +} + +#[cargo_test] +fn multiple_binaries_in_selected_package_with_bin_option_installs_only_one() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/bin/bin1.rs", "fn main() {}") + .file("bar/src/bin/bin2.rs", "fn main() {}") + .build(); + + cargo_process("install --bin bin1 --git") + .arg(p.url().to_string()) + .arg("bar") + .run(); + + let cargo_home = paths::cargo_home(); + assert_has_installed_exe(&cargo_home, "bin1"); + assert_has_not_installed_exe(&cargo_home, "bin2"); +} + +#[cargo_test] +fn multiple_crates_select() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("a/src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .arg("foo") + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_not_installed_exe(paths::cargo_home(), "bar"); + + cargo_process("install --git") + .arg(p.url().to_string()) + .arg("bar") + .run(); + assert_has_installed_exe(paths::cargo_home(), "bar"); +} + +#[cargo_test] +fn multiple_crates_git_all() { + let p = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bin1", "bin2"] + "#, + ) + .file("bin1/Cargo.toml", &basic_manifest("bin1", "0.1.0")) + .file("bin2/Cargo.toml", &basic_manifest("bin2", "0.1.0")) + .file( + "bin1/src/main.rs", + r#"fn main() { println!("Hello, world!"); }"#, + ) + .file( + "bin2/src/main.rs", + r#"fn main() { println!("Hello, world!"); }"#, + ) + .build(); + + cargo_process(&format!("install --git {} bin1 bin2", p.url().to_string())).run(); +} + +#[cargo_test] +fn multiple_crates_auto_binaries() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { path = "a" } + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() {}") + .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("a/src/lib.rs", "") + .build(); + + cargo_process("install --path").arg(p.root()).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn multiple_crates_auto_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { path = "a" } + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file( + "examples/foo.rs", + " + extern crate bar; + extern crate foo; + fn main() {} + ", + ) + .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("a/src/lib.rs", "") + .build(); + + cargo_process("install --path") + .arg(p.root()) + .arg("--example=foo") + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn no_binaries_or_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("a/src/lib.rs", "") + .build(); + + cargo_process("install --path") + .arg(p.root()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no packages found with binaries or examples + +"#]]) + .run(); +} + +#[cargo_test] +fn no_binaries() { + let p = project() + .file("src/lib.rs", "") + .file("examples/foo.rs", "fn main() {}") + .build(); + + cargo_process("install --path") + .arg(p.root()) + .arg("foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] there is nothing to install in `foo v0.0.1 ([ROOT]/foo)`, because it has no binaries +`cargo install` is only for installing programs, and can't be used with libraries. +To use a library crate, add it as a dependency to a Cargo project with `cargo add`. + +"#]]) + .run(); +} + +#[cargo_test] +fn examples() { + let p = project() + .file("src/lib.rs", "") + .file("examples/foo.rs", "extern crate foo; fn main() {}") + .build(); + + cargo_process("install --path") + .arg(p.root()) + .arg("--example=foo") + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn install_force() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + cargo_process("install --path").arg(p.root()).run(); + + let p = project() + .at("foo2") + .file("Cargo.toml", &basic_manifest("foo", "0.2.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --force --path") + .arg(p.root()) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.2.0 ([ROOT]/foo2) +[COMPILING] foo v0.2.0 ([ROOT]/foo2) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo2)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + cargo_process("install --list") + .with_stdout_data(str![[r#" +foo v0.2.0 ([ROOT]/foo2): + foo[EXE] + +"#]]) + .run(); +} + +#[cargo_test] +fn install_force_partial_overlap() { + let p = project() + .file("src/bin/foo-bin1.rs", "fn main() {}") + .file("src/bin/foo-bin2.rs", "fn main() {}") + .build(); + + cargo_process("install --path").arg(p.root()).run(); + + let p = project() + .at("foo2") + .file("Cargo.toml", &basic_manifest("foo", "0.2.0")) + .file("src/bin/foo-bin2.rs", "fn main() {}") + .file("src/bin/foo-bin3.rs", "fn main() {}") + .build(); + + cargo_process("install --force --path") + .arg(p.root()) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.2.0 ([ROOT]/foo2) +[COMPILING] foo v0.2.0 ([ROOT]/foo2) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo-bin3[EXE] +[REPLACING] [ROOT]/home/.cargo/bin/foo-bin2[EXE] +[REMOVING] executable `[ROOT]/home/.cargo/bin/foo-bin1[EXE]` from previous version foo v0.0.1 ([ROOT]/foo) +[INSTALLED] package `foo v0.2.0 ([ROOT]/foo2)` (executable `foo-bin3[EXE]`) +[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo2)` (executable `foo-bin2[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + cargo_process("install --list") + .with_stdout_data(str![[r#" +foo v0.2.0 ([ROOT]/foo2): + foo-bin2[EXE] + foo-bin3[EXE] + +"#]]) + .run(); +} + +#[cargo_test] +fn install_force_bin() { + let p = project() + .file("src/bin/foo-bin1.rs", "fn main() {}") + .file("src/bin/foo-bin2.rs", "fn main() {}") + .build(); + + cargo_process("install --path").arg(p.root()).run(); + + let p = project() + .at("foo2") + .file("Cargo.toml", &basic_manifest("foo", "0.2.0")) + .file("src/bin/foo-bin1.rs", "fn main() {}") + .file("src/bin/foo-bin2.rs", "fn main() {}") + .build(); + + cargo_process("install --force --bin foo-bin2 --path") + .arg(p.root()) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.2.0 ([ROOT]/foo2) +[COMPILING] foo v0.2.0 ([ROOT]/foo2) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo-bin2[EXE] +[REPLACED] package `foo v0.0.1 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo2)` (executable `foo-bin2[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + cargo_process("install --list") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo): + foo-bin1[EXE] +foo v0.2.0 ([ROOT]/foo2): + foo-bin2[EXE] + +"#]]) + .run(); +} + +#[cargo_test] +fn compile_failure() { + let p = project().file("src/main.rs", "").build(); + + cargo_process("install --path") + .arg(p.root()) + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error +[ERROR] failed to compile `foo v0.0.1 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`. +To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path. +... +"#]]) + .run(); +} + +#[cargo_test] +fn git_repo() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + // Use `--locked` to test that we don't even try to write a lock file. + cargo_process("install --locked --git") + .arg(p.url().to_string()) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/foo` +[WARNING] no Cargo.lock file published in foo v0.1.0 ([ROOTURL]/foo#[..]) +[INSTALLING] foo v0.1.0 ([ROOTURL]/foo#[..]) +[COMPILING] foo v0.1.0 ([ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..]) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.1.0 ([ROOTURL]/foo#[..])` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +#[cfg(target_os = "linux")] +fn git_repo_with_lowercase_cargo_toml() { + let p = git::repo(&paths::root().join("foo")) + .file("cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository [..] +[ERROR] Could not find Cargo.toml in `[..]`, but found cargo.toml please try to rename it to Cargo.toml + +"#]] + ) + .run(); +} + +#[cargo_test] +fn list() { + pkg("foo", "0.0.1"); + pkg("bar", "0.2.1"); + pkg("bar", "0.2.2"); + + cargo_process("install --list").with_stdout_data("").run(); + + cargo_process("install bar --version =0.2.1").run(); + cargo_process("install foo").run(); + cargo_process("install --list") + .with_stdout_data(str![[r#" +bar v0.2.1: + bar[EXE] +foo v0.0.1: + foo[EXE] + +"#]]) + .run(); +} + +#[cargo_test] +fn list_error() { + pkg("foo", "0.0.1"); + cargo_process("install foo").run(); + cargo_process("install --list") + .with_stdout_data(str![[r#" +foo v0.0.1: + foo[EXE] + +"#]]) + .run(); + let mut worldfile_path = paths::cargo_home(); + worldfile_path.push(".crates.toml"); + let mut worldfile = OpenOptions::new() + .write(true) + .open(worldfile_path) + .expect(".crates.toml should be there"); + worldfile.write_all(b"\x00").unwrap(); + drop(worldfile); + cargo_process("install --list --verbose") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse crate metadata at `[ROOT]/home/.cargo/.crates.toml` + +Caused by: + invalid TOML found for metadata + +Caused by: + TOML parse error at line 1, column 1 + | + 1 | v1] + | ^ + invalid key + +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall_pkg_does_not_exist() { + cargo_process("uninstall foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `foo` did not match any packages + +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall_bin_does_not_exist() { + pkg("foo", "0.0.1"); + + cargo_process("install foo").run(); + cargo_process("uninstall foo --bin=bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] binary `bar[EXE]` not installed as part of `foo v0.0.1` + +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall_piecemeal() { + let p = project() + .file("src/bin/foo.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .build(); + + cargo_process("install --path").arg(p.root()).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_installed_exe(paths::cargo_home(), "bar"); + + cargo_process("uninstall foo --bin=bar") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE] + +"#]]) + .run(); + + assert_has_installed_exe(paths::cargo_home(), "foo"); + assert_has_not_installed_exe(paths::cargo_home(), "bar"); + + cargo_process("uninstall foo --bin=foo") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + + cargo_process("uninstall foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `foo` did not match any packages + +"#]]) + .run(); +} + +#[cargo_test] +fn subcommand_works_out_of_the_box() { + Package::new("cargo-foo", "1.0.0") + .file("src/main.rs", r#"fn main() { println!("bar"); }"#) + .publish(); + cargo_process("install cargo-foo").run(); + cargo_process("foo") + .with_stdout_data(str![[r#" +bar + +"#]]) + .run(); + cargo_process("--list") + .with_stdout_data(str![[r#" +... + foo +... +"#]]) + .run(); +} + +#[cargo_test] +fn installs_from_cwd_by_default() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("install").with_stderr_data(str![[r#" +[WARNING] Using `cargo install` to install the binaries from the package in current working directory is deprecated, use `cargo install --path .` instead. Use `cargo build` if you want to simply build the package. +... +"#]]).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn installs_from_cwd_with_2018_warnings() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + edition = "2018" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("install") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Using `cargo install` to install the binaries from the package in current working directory is no longer supported, use `cargo install --path .` instead. Use `cargo build` if you want to simply build the package. + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn uninstall_cwd() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("install --path .").with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + + p.cargo("uninstall") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn uninstall_cwd_not_installed() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("uninstall") + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] package `foo v0.0.1 ([ROOT]/foo)` is not installed + +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall_cwd_no_project() { + cargo_process("uninstall") + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] failed to read `[ROOT]/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn do_not_rebuilds_on_local_install() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("build --release").run(); + cargo_process("install --path") + .arg(p.root()) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1 ([ROOT]/foo)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + assert!(p.build_dir().exists()); + assert!(p.release_bin("foo").exists()); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn reports_unsuccessful_subcommand_result() { + Package::new("cargo-fail", "1.0.0") + .file("src/main.rs", r#"fn main() { panic!("EXPLICIT PANIC!"); }"#) + .publish(); + cargo_process("install cargo-fail").run(); + cargo_process("--list") + .with_stdout_data(str![[r#" +... + fail +... +"#]]) + .run(); + cargo_process("fail") + .with_status(101) + .with_stderr_data("...\n[..]EXPLICIT PANIC![..]\n...") + .run(); +} + +#[cargo_test] +fn git_with_lockfile() { + let p = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "fn main() {}") + .file( + "Cargo.lock", + r#" + [[package]] + name = "foo" + version = "0.1.0" + dependencies = [ "bar 0.1.0" ] + + [[package]] + name = "bar" + version = "0.1.0" + "#, + ) + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .run(); +} + +#[cargo_test] +fn q_silences_warnings() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + cargo_process("install -q --path") + .arg(p.root()) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn readonly_dir() { + pkg("foo", "0.0.1"); + + let root = paths::root(); + let dir = &root.join("readonly"); + fs::create_dir(root.join("readonly")).unwrap(); + let mut perms = fs::metadata(dir).unwrap().permissions(); + perms.set_readonly(true); + fs::set_permissions(dir, perms).unwrap(); + + cargo_process("install foo").cwd(dir).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn use_path_workspace() { + Package::new("foo", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [workspace] + members = ["baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + authors = [] + + [dependencies] + foo = "1" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + let lock = p.read_lockfile(); + p.cargo("install").run(); + let lock2 = p.read_lockfile(); + assert_eq!(lock, lock2, "different lockfiles"); +} + +#[cargo_test] +fn path_install_workspace_root_despite_default_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "ws-root" + version = "0.1.0" + authors = [] + + [workspace] + members = ["ws-member"] + default-members = ["ws-member"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "ws-member/Cargo.toml", + r#" + [package] + name = "ws-member" + version = "0.1.0" + authors = [] + "#, + ) + .file("ws-member/src/main.rs", "fn main() {}") + .build(); + + p.cargo("install --path") + .arg(p.root()) + .arg("ws-root") + .with_stderr_data(str![[r#" +[INSTALLING] ws-root v0.1.0 ([ROOT]/foo) +[COMPILING] ws-root v0.1.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/ws-root[EXE] +[INSTALLED] package `ws-root v0.1.0 ([ROOT]/foo)` (executable `ws-root[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + // Particularly avoid "Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)": + .with_stderr_does_not_contain("ws-member") + .run(); +} + +#[cargo_test] +fn git_install_workspace_root_despite_default_members() { + let p = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "ws-root" + version = "0.1.0" + authors = [] + + [workspace] + members = ["ws-member"] + default-members = ["ws-member"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "ws-member/Cargo.toml", + r#" + [package] + name = "ws-member" + version = "0.1.0" + authors = [] + "#, + ) + .file("ws-member/src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .arg("ws-root") + .with_stderr_data(str![[r#" +... +[INSTALLED] package `ws-root v0.1.0 ([ROOTURL]/foo#[..])` (executable `ws-root[EXE]`) +... +"#]]) + // Particularly avoid "Installed package `ws-root v0.1.0 ([..]])` (executable `ws-member`)": + .with_stderr_does_not_contain("ws-member") + .run(); +} + +#[cargo_test] +fn dev_dependencies_no_check() { + Package::new("foo", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dev-dependencies] + baz = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] no matching package named `baz` found +... +"#]]) + .run(); + p.cargo("install").run(); +} + +#[cargo_test] +fn dev_dependencies_lock_file_untouched() { + Package::new("foo", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dev-dependencies] + bar = { path = "a" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("a/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + let lock = p.read_lockfile(); + p.cargo("install").run(); + let lock2 = p.read_lockfile(); + assert!(lock == lock2, "different lockfiles"); +} + +#[cargo_test] +fn install_target_native() { + pkg("foo", "0.1.0"); + + cargo_process("install foo --target") + .arg(cargo_test_support::rustc_host()) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn install_target_foreign() { + if cross_compile::disabled() { + return; + } + + pkg("foo", "0.1.0"); + + cargo_process("install foo --target") + .arg(cross_compile::alternate()) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn vers_precise() { + pkg("foo", "0.1.1"); + pkg("foo", "0.1.2"); + + cargo_process("install foo --vers 0.1.1") + .with_stderr_data(str![[r#" +... +[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`) +... +"#]]) + .run(); +} + +#[cargo_test] +fn version_precise() { + pkg("foo", "0.1.1"); + pkg("foo", "0.1.2"); + + cargo_process("install foo --version 0.1.1") + .with_stderr_data(str![[r#" +... +[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`) +... +"#]]) + .run(); +} + +#[cargo_test] +fn inline_version_precise() { + pkg("foo", "0.1.1"); + pkg("foo", "0.1.2"); + + cargo_process("install foo@0.1.1") + .with_stderr_data(str![[r#" +... +[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`) +... +"#]]) + .run(); +} + +#[cargo_test] +fn inline_version_multiple() { + pkg("foo", "0.1.0"); + pkg("foo", "0.1.1"); + pkg("foo", "0.1.2"); + pkg("bar", "0.2.0"); + pkg("bar", "0.2.1"); + pkg("bar", "0.2.2"); + + cargo_process("install foo@0.1.1 bar@0.2.1") + .with_stderr_data(str![[r#" +... +[DOWNLOADED] foo v0.1.1 (registry `dummy-registry`) +... +[DOWNLOADED] bar v0.2.1 (registry `dummy-registry`) +... +"#]]) + .run(); +} + +#[cargo_test] +fn inline_version_without_name() { + pkg("foo", "0.1.1"); + pkg("foo", "0.1.2"); + + cargo_process("install @0.1.1") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] invalid value '@0.1.1' for '[CRATE[@]]...': missing crate name before '@' + +For more information, try '--help'. + +"#]]) + .run(); +} + +#[cargo_test] +fn inline_and_explicit_version() { + pkg("foo", "0.1.1"); + pkg("foo", "0.1.2"); + + cargo_process("install foo@0.1.1 --version 0.1.1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify both `@` and `--version ` + +"#]]) + .run(); +} + +#[cargo_test] +fn not_both_vers_and_version() { + pkg("foo", "0.1.1"); + pkg("foo", "0.1.2"); + + cargo_process("install foo --version 0.1.1 --vers 0.1.2") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--version ' cannot be used multiple times + +Usage: cargo[EXE] install [OPTIONS] [CRATE[@]]... + +For more information, try '--help'. + +"#]]) + .run(); +} + +#[cargo_test] +fn test_install_git_cannot_be_a_base_url() { + cargo_process("install --git github.com:rust-lang/rustfmt.git") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid url `github.com:rust-lang/rustfmt.git`: cannot-be-a-base-URLs are not supported + +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall_multiple_and_specifying_bin() { + cargo_process("uninstall foo bar --bin baz") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] A binary can only be associated with a single installed package, specifying multiple specs with --bin is redundant. + +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall_with_empty_package_option() { + cargo_process("uninstall -p") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] "--package " requires a SPEC format value. +Run `cargo help pkgid` for more information about SPEC format. + +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall_multiple_and_some_pkg_does_not_exist() { + pkg("foo", "0.0.1"); + + cargo_process("install foo").run(); + + cargo_process("uninstall foo bar") + .with_status(101) + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] +[ERROR] package ID specification `bar` did not match any packages +[SUMMARY] Successfully uninstalled foo! Failed to uninstall bar (see error(s) above). +[ERROR] some packages failed to uninstall + +"#]]) + .run(); + + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + assert_has_not_installed_exe(paths::cargo_home(), "bar"); +} + +#[cargo_test] +fn custom_target_dir_for_git_source() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + cargo_process("install --git") + .arg(p.url().to_string()) + .run(); + assert!(!paths::root().join("target/release").is_dir()); + + cargo_process("install --force --git") + .arg(p.url().to_string()) + .env("CARGO_TARGET_DIR", "target") + .run(); + assert!(paths::root().join("target/release").is_dir()); +} + +#[cargo_test] +fn install_respects_lock_file() { + // `cargo install` now requires --locked to use a Cargo.lock. + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.1") + .file("src/lib.rs", "not rust") + .publish(); + Package::new("foo", "0.1.0") + .dep("bar", "0.1") + .file("src/lib.rs", "") + .file( + "src/main.rs", + "extern crate foo; extern crate bar; fn main() {}", + ) + .file( + "Cargo.lock", + r#" +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] +"#, + ) + .publish(); + + cargo_process("install foo") + .with_stderr_data(str![[r#" +... +[..]not rust[..] +... +"#]]) + .with_status(101) + .run(); + cargo_process("install --locked foo").run(); +} + +#[cargo_test] +fn install_path_respects_lock_file() { + // --path version of install_path_respects_lock_file, --locked is required + // to use Cargo.lock. + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.1") + .file("src/lib.rs", "not rust") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() {}") + .file( + "Cargo.lock", + r#" +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] +"#, + ) + .build(); + + p.cargo("install --path .") + .with_stderr_data(str![[r#" +... +[..]not rust[..] +... +"#]]) + .with_status(101) + .run(); + p.cargo("install --path . --locked").run(); +} + +#[cargo_test] +fn lock_file_path_deps_ok() { + Package::new("bar", "0.1.0").publish(); + + Package::new("foo", "0.1.0") + .dep("bar", "0.1") + .file("src/lib.rs", "") + .file( + "src/main.rs", + "extern crate foo; extern crate bar; fn main() {}", + ) + .file( + "Cargo.lock", + r#" + [[package]] + name = "bar" + version = "0.1.0" + + [[package]] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar 0.1.0", + ] + "#, + ) + .publish(); + + cargo_process("install foo").run(); +} + +#[cargo_test] +fn install_empty_argument() { + // Bug 5229 + cargo_process("install") + .arg("") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] invalid value '' for '[CRATE[@]]...': crate name is empty + +For more information, try '--help'. + +"#]]) + .run(); +} + +#[cargo_test] +fn git_repo_replace() { + let p = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + let repo = git2::Repository::open(&p.root()).unwrap(); + let old_rev = repo.revparse_single("HEAD").unwrap().id(); + cargo_process("install --git") + .arg(p.url().to_string()) + .run(); + git::commit(&repo); + let new_rev = repo.revparse_single("HEAD").unwrap().id(); + let mut path = paths::home(); + path.push(".cargo/.crates.toml"); + + assert_ne!(old_rev, new_rev); + assert!(fs::read_to_string(path.clone()) + .unwrap() + .contains(&format!("{}", old_rev))); + cargo_process("install --force --git") + .arg(p.url().to_string()) + .run(); + assert!(fs::read_to_string(path) + .unwrap() + .contains(&format!("{}", new_rev))); +} + +#[cargo_test] +fn workspace_uses_workspace_target_dir() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [workspace] + + [dependencies] + bar = { path = 'bar' } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release").cwd("bar").run(); + cargo_process("install --path") + .arg(p.root().join("bar")) + .with_stderr_data(str![[r#" +[INSTALLING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE] +[INSTALLED] package `bar v0.1.0 ([ROOT]/foo/bar)` (executable `bar[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn install_ignores_local_cargo_config() { + pkg("bar", "0.0.1"); + + let p = project() + .file( + ".cargo/config.toml", + r#" + [build] + target = "non-existing-target" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("install bar").run(); + assert_has_installed_exe(paths::cargo_home(), "bar"); +} + +#[cargo_test] +fn install_ignores_unstable_table_in_local_cargo_config() { + pkg("bar", "0.0.1"); + + let p = project() + .file( + ".cargo/config.toml", + r#" + [unstable] + build-std = ["core"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("install bar") + .masquerade_as_nightly_cargo(&["build-std"]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "bar"); +} + +#[cargo_test] +fn install_global_cargo_config() { + pkg("bar", "0.0.1"); + + let config = paths::cargo_home().join("config.toml"); + let mut toml = fs::read_to_string(&config).unwrap_or_default(); + + toml.push_str( + r#" + [build] + target = 'nonexistent' + "#, + ); + fs::write(&config, toml).unwrap(); + + cargo_process("install bar") + .with_status(101) + .with_stderr_data( + str![[r#" +[INSTALLING] bar v0.0.1 +Caused by: + process didn't exit successfully: `rustc [..]--target nonexistent[..]` ([EXIT_STATUS]: 1) +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn install_path_config() { + project() + .file( + ".cargo/config.toml", + r#" + [build] + target = 'nonexistent' + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + cargo_process("install --path foo") + .with_status(101) + .with_stderr_data(str![[r#" +... + process didn't exit successfully: `rustc [..]--target nonexistent[..]` ([EXIT_STATUS]: 1) +... +"#]]) + .run(); +} + +#[cargo_test] +fn install_version_req() { + // Try using a few versionreq styles. + pkg("foo", "0.0.3"); + pkg("foo", "1.0.4"); + pkg("foo", "1.0.5"); + cargo_process("install foo --version=*") + .with_stderr_does_not_contain("[WARNING][..]is not a valid semver[..]") + .with_stderr_data(str![[r#" +... +[INSTALLING] foo v1.0.5 +... +"#]]) + .run(); + cargo_process("uninstall foo").run(); + cargo_process("install foo --version=^1.0") + .with_stderr_does_not_contain("[WARNING][..]is not a valid semver[..]") + .with_stderr_data(str![[r#" +... +[INSTALLING] foo v1.0.5 +... +"#]]) + .run(); + cargo_process("uninstall foo").run(); + cargo_process("install foo --version=0.0.*") + .with_stderr_does_not_contain("[WARNING][..]is not a valid semver[..]") + .with_stderr_data(str![[r#" +... +[INSTALLING] foo v0.0.3 +... +"#]]) + .run(); +} + +#[cargo_test] +fn git_install_reads_workspace_manifest() { + let p = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bin1"] + + [profile.release] + incremental = 3 + "#, + ) + .file("bin1/Cargo.toml", &basic_manifest("bin1", "0.1.0")) + .file( + "bin1/src/main.rs", + r#"fn main() { println!("Hello, world!"); }"#, + ) + .build(); + + cargo_process(&format!("install --git {}", p.url().to_string())) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/foo` +[ERROR] invalid type: integer `3`, expected a boolean + --> home/.cargo/git/checkouts/foo-[HASH]/[..]/Cargo.toml:6:27 + | +6 | incremental = 3 + | ^ + | +[ERROR] invalid type: integer `3`, expected a boolean + --> home/.cargo/git/checkouts/foo-[HASH]/[..]/Cargo.toml:6:27 + | +6 | incremental = 3 + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn install_git_with_symlink_home() { + // Ensure that `cargo install` with a git repo is OK when CARGO_HOME is a + // symlink, and uses an build script. + if !symlink_supported() { + return; + } + let p = git::new("foo", |p| { + p.file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + // This triggers discover_git_and_list_files for detecting changed files. + .file("build.rs", "fn main() {}") + }); + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(windows)] + use std::os::windows::fs::symlink_dir as symlink; + + let actual = paths::root().join("actual-home"); + t!(std::fs::create_dir(&actual)); + t!(symlink(&actual, paths::home().join(".cargo"))); + cargo_process("install --git") + .arg(p.url().to_string()) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/foo` +[INSTALLING] foo v1.0.0 ([ROOTURL]/foo#[..]) +[COMPILING] foo v1.0.0 ([ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..]) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v1.0.0 ([ROOTURL]/foo#[..])` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn install_yanked_cargo_package() { + Package::new("baz", "0.0.1").yanked(true).publish(); + cargo_process("install baz --version 0.0.1") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] cannot install package `baz`, it has been yanked from registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn install_cargo_package_in_a_patched_workspace() { + pkg("foo", "0.1.0"); + pkg("fizz", "1.0.0"); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [workspace] + members = ["baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + authors = [] + + [dependencies] + fizz = "1" + + [patch.crates-io] + fizz = { version = "=1.0.0" } + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] patch for the non root package will be ignored, specify patch at the workspace root: +package: [ROOT]/foo/baz/Cargo.toml +workspace: [ROOT]/foo/Cargo.toml +... +"#]]) + .run(); + + // A crate installation must not emit any message from a workspace under + // current working directory. + // See https://github.com/rust-lang/cargo/issues/8619 + p.cargo("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`) +[INSTALLING] foo v0.1.0 +[COMPILING] foo v0.1.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.1.0` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn locked_install_without_published_lockfile() { + Package::new("foo", "0.1.0") + .file("src/main.rs", "//! Some docs\nfn main() {}") + .publish(); + + cargo_process("install foo --locked") + .with_stderr_data(str![[r#" +... +[WARNING] no Cargo.lock file published in foo v0.1.0 +... +"#]]) + .run(); +} + +#[cargo_test] +fn install_semver_metadata() { + // Check trying to install a package that uses semver metadata. + // This uses alt registry because the bug this is exercising doesn't + // trigger with a replaced source. + registry::alt_init(); + Package::new("foo", "1.0.0+abc") + .alternative(true) + .file("src/main.rs", "fn main() {}") + .publish(); + + cargo_process("install foo --registry alternative --version 1.0.0+abc").run(); + cargo_process("install foo --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[IGNORED] package `foo v1.0.0+abc (registry `alternative`)` is already installed, use --force to override +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + // "Updating" is not displayed here due to the --version fast-path. + cargo_process("install foo --registry alternative --version 1.0.0+abc") + .with_stderr_data(str![[r#" +[IGNORED] package `foo v1.0.0+abc (registry `alternative`)` is already installed, use --force to override +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + cargo_process("install foo --registry alternative --version 1.0.0 --force") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[INSTALLING] foo v1.0.0+abc (registry `alternative`) +[COMPILING] foo v1.0.0+abc (registry `alternative`) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v1.0.0+abc (registry `alternative`)` with `foo v1.0.0+abc (registry `alternative`)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + // Check that from a fresh cache will work without metadata, too. + paths::home().join(".cargo/registry").rm_rf(); + paths::home().join(".cargo/bin").rm_rf(); + cargo_process("install foo --registry alternative --version 1.0.0") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v1.0.0+abc (registry `alternative`) +[INSTALLING] foo v1.0.0+abc (registry `alternative`) +[COMPILING] foo v1.0.0+abc (registry `alternative`) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v1.0.0+abc (registry `alternative`)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn no_auto_fix_note() { + Package::new("auto_fix", "0.0.1") + .file("src/lib.rs", "use std::io;") + .file( + "src/main.rs", + &format!("extern crate {}; use std::io; fn main() {{}}", "auto_fix"), + ) + .publish(); + + // This should not contain a suggestion to run `cargo fix` + // + // This is checked by matching the full output as `with_stderr_does_not_contain` + // can be brittle + cargo_process("install auto_fix") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] auto_fix v0.0.1 (registry `dummy-registry`) +[INSTALLING] auto_fix v0.0.1 +[COMPILING] auto_fix v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/auto_fix[EXE] +[INSTALLED] package `auto_fix v0.0.1` (executable `auto_fix[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "auto_fix"); + + cargo_process("uninstall auto_fix") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/auto_fix[EXE] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "auto_fix"); +} + +#[cargo_test] +fn failed_install_retains_temp_directory() { + // Verifies that the temporary directory persists after a build failure. + Package::new("foo", "0.0.1") + .file("src/main.rs", "x") + .publish(); + let err = cargo_process("install foo").exec_with_output().unwrap_err(); + let err = err.downcast::().unwrap(); + let stderr = String::from_utf8(err.stderr.unwrap()).unwrap(); + assert_e2e().eq(&stderr, str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[ERROR] expected one of `!` or `::`, found `` + --> [ROOT]/home/.cargo/registry/src/-[..]/foo-0.0.1/src/main.rs:1:1 + | +1 | x + | ^ expected one of `!` or `::` + +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error +[ERROR] failed to compile `foo v0.0.1`, intermediate artifacts can be found at `[..]`. +To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path. + +"#]]); + + // Find the path in the output. + 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()); +} + +#[cargo_test] +fn sparse_install() { + // Checks for an issue where uninstalling something corrupted + // the SourceIds of sparse registries. + // See https://github.com/rust-lang/cargo/issues/11751 + let _registry = registry::RegistryBuilder::new().http_index().build(); + + pkg("foo", "0.0.1"); + pkg("bar", "0.0.1"); + + cargo_process("install foo --registry dummy-registry") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 (registry `dummy-registry`) +[UPDATING] `dummy-registry` index +[COMPILING] foo v0.0.1 (registry `dummy-registry`) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1 (registry `dummy-registry`)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + let assert_v1 = |expected| { + let v1 = fs::read_to_string(paths::home().join(".cargo/.crates.toml")).unwrap(); + assert_e2e().eq(&v1, expected); + }; + assert_v1(str![[r#" +[v1] +"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)" = ["foo[EXE]"] + +"#]]); + cargo_process("install bar").run(); + assert_has_installed_exe(paths::cargo_home(), "bar"); + assert_v1(str![[r#" +[v1] +"bar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = ["bar[EXE]"] +"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)" = ["foo[EXE]"] + +"#]]); + + cargo_process("uninstall bar") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/bar[EXE] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "bar"); + assert_v1(str![[r#" +[v1] +"foo 0.0.1 (sparse+http://127.0.0.1:[..]/index/)" = ["foo[EXE]"] + +"#]]); + cargo_process("uninstall foo") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + assert_v1(str![[r#" +[v1] + +"#]]); +} + +#[cargo_test] +fn self_referential() { + // Some packages build-dep on prior versions of themselves. + Package::new("foo", "0.0.1") + .file("src/lib.rs", "fn hello() {}") + .file("src/main.rs", "fn main() {}") + .file("build.rs", "fn main() {}") + .publish(); + Package::new("foo", "0.0.2") + .file("src/lib.rs", "fn hello() {}") + .file("src/main.rs", "fn main() {}") + .file("build.rs", "fn main() {}") + .build_dep("foo", "0.0.1") + .publish(); + + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.2 (registry `dummy-registry`) +[INSTALLING] foo v0.0.2 +[LOCKING] 1 package to latest compatible version +[ADDING] foo v0.0.1 (available: v0.0.2) +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[COMPILING] foo v0.0.1 +[COMPILING] foo v0.0.2 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.2` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn ambiguous_registry_vs_local_package() { + // Correctly install 'foo' from a local package, even if that package also + // depends on a registry dependency named 'foo'. + Package::new("foo", "0.0.1") + .file("src/lib.rs", "fn hello() {}") + .publish(); + + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + edition = "2021" + + [dependencies] + foo = "0.0.1" + "#, + ) + .build(); + + cargo_process("install --path") + .arg(p.root()) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.1.0 ([ROOT]/foo) +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[COMPILING] foo v0.0.1 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.1.0 ([ROOT]/foo)` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn install_with_redundant_default_mode() { + pkg("foo", "0.0.1"); + + cargo_process("install foo --release") + .with_stderr_data(str![[r#" +[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(); +} + +#[cargo_test] +fn install_incompat_msrv() { + Package::new("foo", "0.1.0") + .file("src/main.rs", "fn main() {}") + .rust_version("1.30") + .publish(); + Package::new("foo", "0.2.0") + .file("src/main.rs", "fn main() {}") + .rust_version("1.9876.0") + .publish(); + + cargo_process("install foo") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] cannot install package `foo 0.2.0`, it requires rustc 1.9876.0 or newer, while the currently active rustc version is [..] +`foo 0.1.0` supports rustc 1.30 + +"#]]) + .with_status(101) + .run(); +} + +fn assert_tracker_noexistence(key: &str) { + let v1_data: toml::Value = + toml::from_str(&fs::read_to_string(paths::cargo_home().join(".crates.toml")).unwrap()) + .unwrap(); + let v2_data: serde_json::Value = serde_json::from_str( + &fs::read_to_string(paths::cargo_home().join(".crates2.json")).unwrap(), + ) + .unwrap(); + + assert!(v1_data["v1"].get(key).is_none()); + assert!(v2_data["installs"][key].is_null()); +} + +#[cargo_test] +fn uninstall_running_binary() { + use std::io::Write; + + Package::new("foo", "0.0.1") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + "#, + ) + .file( + "src/main.rs", + r#" + use std::net::TcpStream; + use std::env::var; + use std::io::Read; + fn main() { + for i in 0..2 { + TcpStream::connect(&var("__ADDR__").unwrap()[..]) + .unwrap() + .read_to_end(&mut Vec::new()) + .unwrap(); + } + } + "#, + ) + .publish(); + + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + + let foo_bin = paths::cargo_home().join("bin").join(exe("foo")); + let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = l.local_addr().unwrap().to_string(); + let t = thread::spawn(move || { + ProcessBuilder::new(foo_bin) + .env("__ADDR__", addr) + .exec() + .unwrap(); + }); + let key = "foo 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)"; + + #[cfg(windows)] + { + // Ensure foo is running before the first `cargo uninstall` call + l.accept().unwrap().0.write_all(&[1]).unwrap(); + cargo_process("uninstall foo") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] failed to remove file `[ROOT]/home/.cargo/bin/foo[EXE]` +... +"#]]) + .run(); + // Ensure foo is stopped before the second `cargo uninstall` call + l.accept().unwrap().0.write_all(&[1]).unwrap(); + t.join().unwrap(); + cargo_process("uninstall foo") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] + +"#]]) + .run(); + }; + + #[cfg(not(windows))] + { + // Ensure foo is running before the first `cargo uninstall` call + l.accept().unwrap().0.write_all(&[1]).unwrap(); + cargo_process("uninstall foo") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/foo[EXE] + +"#]]) + .run(); + l.accept().unwrap().0.write_all(&[1]).unwrap(); + t.join().unwrap(); + }; + + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + assert_tracker_noexistence(key); + + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[INSTALLING] foo v0.0.1 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); +} + +#[cargo_test] +fn dry_run() { + pkg("foo", "0.0.1"); + + cargo_process("-Z unstable-options install --dry-run foo") + .masquerade_as_nightly_cargo(&["install::dry-run"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[WARNING] aborting install due to dry run +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn dry_run_incompatible_package() { + Package::new("some-package-from-the-distant-future", "0.0.1") + .rust_version("1.2345.0") + .file("src/main.rs", "fn main() {}") + .publish(); + + cargo_process("-Z unstable-options install --dry-run some-package-from-the-distant-future") + .masquerade_as_nightly_cargo(&["install::dry-run"]) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] cannot install package `some-package-from-the-distant-future 0.0.1`, it requires rustc 1.2345.0 or newer, while the currently active rustc version is [..] + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "some-package-from-the-distant-future"); +} + +#[cargo_test] +fn dry_run_incompatible_package_dependecy() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + some-package-from-the-distant-future = { path = "a" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "a/Cargo.toml", + r#" + [package] + name = "some-package-from-the-distant-future" + version = "0.1.0" + authors = [] + rust-version = "1.2345.0" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + cargo_process("-Z unstable-options install --dry-run --path") + .arg(p.root()) + .arg("foo") + .masquerade_as_nightly_cargo(&["install::dry-run"]) + .with_status(101) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.1.0 ([ROOT]/foo) +[LOCKING] 1 package to latest compatible version +[ERROR] failed to compile `foo v0.1.0 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`. +To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path. + +Caused by: + rustc [..] is not supported by the following package: + some-package-from-the-distant-future@0.1.0 requires rustc 1.2345.0 + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn dry_run_upgrade() { + pkg("foo", "0.0.1"); + cargo_process("install foo").run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + + pkg("foo", "0.0.2"); + cargo_process("-Z unstable-options install --dry-run foo") + .masquerade_as_nightly_cargo(&["install::dry-run"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.2 (registry `dummy-registry`) +[INSTALLING] foo v0.0.2 +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[WARNING] aborting install due to dry run +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn dry_run_remove_orphan() { + Package::new("bar", "1.0.0") + .file("src/bin/client.rs", "fn main() {}") + .file("src/bin/server.rs", "fn main() {}") + .publish(); + + cargo_process("install bar") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[INSTALLING] bar v1.0.0 +[COMPILING] bar v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/client[EXE] +[INSTALLING] [ROOT]/home/.cargo/bin/server[EXE] +[INSTALLED] package `bar v1.0.0` (executables `client[EXE]`, `server[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "client"); + assert_has_installed_exe(paths::cargo_home(), "server"); + + Package::new("bar", "2.0.0") + .file("src/bin/client.rs", "fn main() {}") + .publish(); + + cargo_process("-Z unstable-options install --dry-run bar") + .masquerade_as_nightly_cargo(&["install::dry-run"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v2.0.0 (registry `dummy-registry`) +[INSTALLING] bar v2.0.0 +[REPLACING] [ROOT]/home/.cargo/bin/client[EXE] +[REMOVING] executable `[ROOT]/home/.cargo/bin/server[EXE]` from previous version bar v1.0.0 +[WARNING] aborting install due to dry run +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert_has_installed_exe(paths::cargo_home(), "client"); + // Ensure server is still installed after the dry run + assert_has_installed_exe(paths::cargo_home(), "server"); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install_upgrade.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install_upgrade.rs new file mode 100644 index 000000000..fb52e3844 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/install_upgrade.rs @@ -0,0 +1,986 @@ +//! Tests for `cargo install` where it upgrades a package if it is out-of-date. + +use std::collections::BTreeSet; +use std::env; +use std::fs; +use std::path::PathBuf; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use cargo::core::PackageId; +use cargo_test_support::install::exe; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package}; +use cargo_test_support::{ + basic_manifest, cargo_process, cross_compile, execs, git, process, project, str, Execs, +}; + +fn pkg_maybe_yanked(name: &str, vers: &str, yanked: bool) { + Package::new(name, vers) + .yanked(yanked) + .file( + "src/main.rs", + r#"fn main() { println!("{}", env!("CARGO_PKG_VERSION")) }"#, + ) + .publish(); +} + +// Helper for publishing a package. +fn pkg(name: &str, vers: &str) { + pkg_maybe_yanked(name, vers, false) +} + +fn v1_path() -> PathBuf { + paths::cargo_home().join(".crates.toml") +} + +fn v2_path() -> PathBuf { + paths::cargo_home().join(".crates2.json") +} + +fn load_crates1() -> toml::Value { + toml::from_str(&fs::read_to_string(v1_path()).unwrap()).unwrap() +} + +fn load_crates2() -> serde_json::Value { + serde_json::from_str(&fs::read_to_string(v2_path()).unwrap()).unwrap() +} + +fn installed_exe(name: &str) -> PathBuf { + paths::cargo_home().join("bin").join(exe(name)) +} + +/// Helper for executing binaries installed by cargo. +fn installed_process(name: &str) -> Execs { + static NEXT_ID: AtomicUsize = AtomicUsize::new(0); + thread_local!(static UNIQUE_ID: usize = NEXT_ID.fetch_add(1, Ordering::SeqCst)); + + // This copies the executable to a unique name so that it may be safely + // replaced on Windows. See Project::rename_run for details. + let src = installed_exe(name); + let dst = installed_exe(&UNIQUE_ID.with(|my_id| format!("{}-{}", name, my_id))); + // Note: Cannot use copy. On Linux, file descriptors may be left open to + // the executable as other tests in other threads are constantly spawning + // new processes (see https://github.com/rust-lang/cargo/pull/5557 for + // more). + fs::rename(&src, &dst) + .unwrap_or_else(|e| panic!("Failed to rename `{:?}` to `{:?}`: {}", src, dst, e)); + // Leave behind a fake file so that reinstall duplicate check works. + fs::write(src, "").unwrap(); + let p = process(dst); + execs().with_process_builder(p) +} + +/// Check that the given package name/version has the following bins listed in +/// the trackers. Also verifies that both trackers are in sync and valid. +/// Pass in an empty `bins` list to assert that the package is *not* installed. +fn validate_trackers(name: &str, version: &str, bins: &[&str]) { + let v1 = load_crates1(); + let v1_table = v1.get("v1").unwrap().as_table().unwrap(); + let v2 = load_crates2(); + let v2_table = v2["installs"].as_object().unwrap(); + assert_eq!(v1_table.len(), v2_table.len()); + // Convert `bins` to a BTreeSet. + let bins: BTreeSet = bins + .iter() + .map(|b| format!("{}{}", b, env::consts::EXE_SUFFIX)) + .collect(); + // Check every entry matches between v1 and v2. + for (pkg_id_str, v1_bins) in v1_table { + let pkg_id: PackageId = toml::Value::from(pkg_id_str.to_string()) + .try_into() + .unwrap(); + let v1_bins: BTreeSet = v1_bins + .as_array() + .unwrap() + .iter() + .map(|b| b.as_str().unwrap().to_string()) + .collect(); + if pkg_id.name().as_str() == name && pkg_id.version().to_string() == version { + if bins.is_empty() { + panic!( + "Expected {} to not be installed, but found: {:?}", + name, v1_bins + ); + } else { + assert_eq!(bins, v1_bins); + } + } + let pkg_id_value = serde_json::to_value(&pkg_id).unwrap(); + let pkg_id_str = pkg_id_value.as_str().unwrap(); + let v2_info = v2_table + .get(pkg_id_str) + .expect("v2 missing v1 pkg") + .as_object() + .unwrap(); + let v2_bins = v2_info["bins"].as_array().unwrap(); + let v2_bins: BTreeSet = v2_bins + .iter() + .map(|b| b.as_str().unwrap().to_string()) + .collect(); + assert_eq!(v1_bins, v2_bins); + } +} + +#[cargo_test] +fn registry_upgrade() { + // Installing and upgrading from a registry. + pkg("foo", "1.0.0"); + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v1.0.0 (registry `dummy-registry`) +[INSTALLING] foo v1.0.0 +[COMPILING] foo v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v1.0.0` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + installed_process("foo") + .with_stdout_data(str![[r#" +1.0.0 + +"#]]) + .run(); + validate_trackers("foo", "1.0.0", &["foo"]); + + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[IGNORED] package `foo v1.0.0` is already installed, use --force to override +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + + pkg("foo", "1.0.1"); + + cargo_process("install foo").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v1.0.1 (registry `dummy-registry`) +[INSTALLING] foo v1.0.1 +[COMPILING] foo v1.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v1.0.0` with `foo v1.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]).run(); + + installed_process("foo") + .with_stdout_data(str![[r#" +1.0.1 + +"#]]) + .run(); + validate_trackers("foo", "1.0.1", &["foo"]); + + cargo_process("install foo --version=1.0.0") + .with_stderr_data(str![[r#" +... +[COMPILING] foo v1.0.0 +... +"#]]) + .run(); + installed_process("foo") + .with_stdout_data(str![[r#" +1.0.0 + +"#]]) + .run(); + validate_trackers("foo", "1.0.0", &["foo"]); + + cargo_process("install foo --version=^1.0") + .with_stderr_data(str![[r#" +... +[COMPILING] foo v1.0.1 +... +"#]]) + .run(); + installed_process("foo") + .with_stdout_data(str![[r#" +1.0.1 + +"#]]) + .run(); + validate_trackers("foo", "1.0.1", &["foo"]); + + cargo_process("install foo --version=^1.0") + .with_stderr_data(str![[r#" +... +[IGNORED] package `foo v1.0.1` is already installed, use --force to override +... +"#]]) + .run(); +} + +#[cargo_test] +fn uninstall() { + // Basic uninstall test. + pkg("foo", "1.0.0"); + cargo_process("install foo").run(); + cargo_process("uninstall foo").run(); + let data = load_crates2(); + assert_eq!(data["installs"].as_object().unwrap().len(), 0); + let v1_table = load_crates1(); + assert_eq!(v1_table.get("v1").unwrap().as_table().unwrap().len(), 0); +} + +#[cargo_test] +fn upgrade_force() { + pkg("foo", "1.0.0"); + cargo_process("install foo").run(); + cargo_process("install foo --force") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[INSTALLING] foo v1.0.0 +[COMPILING] foo v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v1.0.0` with `foo v1.0.0` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + validate_trackers("foo", "1.0.0", &["foo"]); +} + +#[cargo_test] +fn ambiguous_version_no_longer_allowed() { + // Non-semver-requirement is not allowed for `--version`. + pkg("foo", "1.0.0"); + cargo_process("install foo --version=1.0") + .with_stderr_data(str![[r#" +[ERROR] invalid value '1.0' for '--version ': unexpected end of input while parsing minor version number + + tip: if you want to specify SemVer range, add an explicit qualifier, like '^1.0' + +For more information, try '--help'. + +"#]]) + .with_status(1) + .run(); +} + +#[cargo_test] +fn path_is_always_dirty() { + // --path should always reinstall. + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("install --path .").run(); + p.cargo("install --path .") + .with_stderr_data(str![[r#" +... +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +... +"#]]) + .run(); +} + +#[cargo_test] +fn fails_for_conflicts_unknown() { + // If an untracked file is in the way, it should fail. + pkg("foo", "1.0.0"); + let exe = installed_exe("foo"); + exe.parent().unwrap().mkdir_p(); + fs::write(exe, "").unwrap(); + cargo_process("install foo") + .with_stderr_data(str![[r#" +... +[ERROR] binary `foo[EXE]` already exists in destination +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn fails_for_conflicts_known() { + // If the same binary exists in another package, it should fail. + pkg("foo", "1.0.0"); + Package::new("bar", "1.0.0") + .file("src/bin/foo.rs", "fn main() {}") + .publish(); + cargo_process("install foo").run(); + cargo_process("install bar") + .with_stderr_data(str![[r#" +... +[ERROR] binary `foo[EXE]` already exists in destination as part of `foo v1.0.0` +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn supports_multiple_binary_names() { + // Can individually install with --bin or --example + Package::new("foo", "1.0.0") + .file("src/main.rs", r#"fn main() { println!("foo"); }"#) + .file("src/bin/a.rs", r#"fn main() { println!("a"); }"#) + .file("examples/ex1.rs", r#"fn main() { println!("ex1"); }"#) + .publish(); + cargo_process("install foo --bin foo").run(); + installed_process("foo") + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); + assert!(!installed_exe("a").exists()); + assert!(!installed_exe("ex1").exists()); + validate_trackers("foo", "1.0.0", &["foo"]); + cargo_process("install foo --bin a").run(); + installed_process("a") + .with_stdout_data(str![[r#" +a + +"#]]) + .run(); + assert!(!installed_exe("ex1").exists()); + validate_trackers("foo", "1.0.0", &["a", "foo"]); + cargo_process("install foo --example ex1").run(); + installed_process("ex1") + .with_stdout_data(str![[r#" +ex1 + +"#]]) + .run(); + validate_trackers("foo", "1.0.0", &["a", "ex1", "foo"]); + cargo_process("uninstall foo --bin foo").run(); + assert!(!installed_exe("foo").exists()); + assert!(installed_exe("ex1").exists()); + validate_trackers("foo", "1.0.0", &["a", "ex1"]); + cargo_process("uninstall foo").run(); + assert!(!installed_exe("ex1").exists()); + assert!(!installed_exe("a").exists()); +} + +#[cargo_test] +fn v1_already_installed_fresh() { + // Install with v1, then try to install again with v2. + pkg("foo", "1.0.0"); + cargo_process("install foo").run(); + cargo_process("install foo") + .with_stderr_data(str![[r#" +... +[IGNORED] package `foo v1.0.0` is already installed, use --force to override +... +"#]]) + .run(); +} + +#[cargo_test] +fn v1_already_installed_dirty() { + // Install with v1, then install a new version with v2. + pkg("foo", "1.0.0"); + cargo_process("install foo").run(); + pkg("foo", "1.0.1"); + cargo_process("install foo") + .with_stderr_data(str![[r#" +... +[COMPILING] foo v1.0.1 +... +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +... +"#]]) + .run(); + validate_trackers("foo", "1.0.1", &["foo"]); +} + +#[cargo_test] +fn change_features_rebuilds() { + Package::new("foo", "1.0.0") + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(feature = "f1") { + println!("f1"); + } + if cfg!(feature = "f2") { + println!("f2"); + } + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + + [features] + f1 = [] + f2 = [] + default = ["f1"] + "#, + ) + .publish(); + cargo_process("install foo").run(); + installed_process("foo") + .with_stdout_data(str![[r#" +f1 + +"#]]) + .run(); + cargo_process("install foo --no-default-features").run(); + installed_process("foo").with_stdout_data("").run(); + cargo_process("install foo --all-features").run(); + installed_process("foo") + .with_stdout_data(str![[r#" +f1 +f2 + +"#]]) + .run(); + cargo_process("install foo --no-default-features --features=f1").run(); + installed_process("foo") + .with_stdout_data(str![[r#" +f1 + +"#]]) + .run(); +} + +#[cargo_test] +fn change_profile_rebuilds() { + pkg("foo", "1.0.0"); + cargo_process("install foo").run(); + cargo_process("install foo --debug") + .with_stderr_data(str![[r#" +... +[COMPILING] foo v1.0.0 +... +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +... +"#]]) + .run(); + cargo_process("install foo --debug") + .with_stderr_data(str![[r#" +... +[IGNORED] package `foo v1.0.0` is already installed, use --force to override +... +"#]]) + .run(); +} + +#[cargo_test] +fn change_target_rebuilds() { + if cross_compile::disabled() { + return; + } + pkg("foo", "1.0.0"); + cargo_process("install foo").run(); + let target = cross_compile::alternate(); + cargo_process("install foo -v --target") + .arg(&target) + .with_stderr_data(str![[r#" +... +[COMPILING] foo v1.0.0 +[RUNNING] `rustc [..]--target [ALT_TARGET][..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +... +"#]]) + .run(); +} + +#[cargo_test] +fn change_bin_sets_rebuilds() { + // Changing which bins in a multi-bin project should reinstall. + Package::new("foo", "1.0.0") + .file("src/main.rs", "fn main() { }") + .file("src/bin/x.rs", "fn main() { }") + .file("src/bin/y.rs", "fn main() { }") + .publish(); + cargo_process("install foo --bin x").run(); + assert!(installed_exe("x").exists()); + assert!(!installed_exe("y").exists()); + assert!(!installed_exe("foo").exists()); + validate_trackers("foo", "1.0.0", &["x"]); + cargo_process("install foo --bin y") + .with_stderr_data(str![[r#" +... +[INSTALLED] package `foo v1.0.0` (executable `y[EXE]`) +... +"#]]) + .run(); + assert!(installed_exe("x").exists()); + assert!(installed_exe("y").exists()); + assert!(!installed_exe("foo").exists()); + validate_trackers("foo", "1.0.0", &["x", "y"]); + cargo_process("install foo") + .with_stderr_data(str![[r#" +... +[INSTALLED] package `foo v1.0.0` (executable `foo[EXE]`) +[REPLACED] package `foo v1.0.0` with `foo v1.0.0` (executables `x[EXE]`, `y[EXE]`) +... +"#]]) + .run(); + assert!(installed_exe("x").exists()); + assert!(installed_exe("y").exists()); + assert!(installed_exe("foo").exists()); + validate_trackers("foo", "1.0.0", &["foo", "x", "y"]); +} + +#[cargo_test] +fn forwards_compatible() { + // Unknown fields should be preserved. + pkg("foo", "1.0.0"); + pkg("bar", "1.0.0"); + cargo_process("install foo").run(); + let key = "foo 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"; + let v2 = paths::cargo_home().join(".crates2.json"); + let mut data = load_crates2(); + data["newfield"] = serde_json::Value::Bool(true); + data["installs"][key]["moreinfo"] = serde_json::Value::String("shazam".to_string()); + fs::write(&v2, serde_json::to_string(&data).unwrap()).unwrap(); + cargo_process("install bar").run(); + let data: serde_json::Value = serde_json::from_str(&fs::read_to_string(&v2).unwrap()).unwrap(); + assert_eq!(data["newfield"].as_bool().unwrap(), true); + assert_eq!( + data["installs"][key]["moreinfo"].as_str().unwrap(), + "shazam" + ); +} + +#[cargo_test] +fn v2_syncs() { + // V2 inherits the installs from V1. + pkg("one", "1.0.0"); + pkg("two", "1.0.0"); + pkg("three", "1.0.0"); + let p = project() + .file("src/bin/x.rs", "fn main() {}") + .file("src/bin/y.rs", "fn main() {}") + .build(); + cargo_process("install one").run(); + validate_trackers("one", "1.0.0", &["one"]); + p.cargo("install --path .").run(); + validate_trackers("foo", "1.0.0", &["x", "y"]); + // v1 add/remove + cargo_process("install two").run(); + cargo_process("uninstall one").run(); + // This should pick up that `two` was added, `one` was removed. + cargo_process("install three").run(); + validate_trackers("three", "1.0.0", &["three"]); + cargo_process("install --list") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo): + x[EXE] + y[EXE] +three v1.0.0: + three[EXE] +two v1.0.0: + two[EXE] + +"#]]) + .run(); + cargo_process("install one").run(); + installed_process("one") + .with_stdout_data(str![[r#" +1.0.0 + +"#]]) + .run(); + validate_trackers("one", "1.0.0", &["one"]); + cargo_process("install two") + .with_stderr_data(str![[r#" +... +[IGNORED] package `two v1.0.0` is already installed, use --force to override +... +"#]]) + .run(); + // v1 remove + p.cargo("uninstall --bin x").run(); + pkg("x", "1.0.0"); + pkg("y", "1.0.0"); + // This should succeed because `x` was removed in V1. + cargo_process("install x").run(); + validate_trackers("x", "1.0.0", &["x"]); + // This should fail because `y` still exists in a different package. + cargo_process("install y") + .with_stderr_data(str![[r#" +... +[ERROR] binary `y[EXE]` already exists in destination as part of `foo v0.0.1 ([ROOT]/foo)` +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn upgrade_git() { + let git_project = git::new("foo", |project| project.file("src/main.rs", "fn main() {}")); + // install + cargo_process("install --git") + .arg(git_project.url().to_string()) + .run(); + // Check install stays fresh. + cargo_process("install --git") + .arg(git_project.url().to_string()) + .with_stderr_data(str![[r#" +... +[IGNORED] package `foo v0.0.1 ([ROOTURL]/foo#[..])` is already installed, use --force to override +... +"#]]) + .run(); + // Modify a file. + let repo = git2::Repository::open(git_project.root()).unwrap(); + git_project.change_file("src/main.rs", r#"fn main() {println!("onomatopoeia");}"#); + git::add(&repo); + git::commit(&repo); + // Install should reinstall. + cargo_process("install --git") + .arg(git_project.url().to_string()) + .with_stderr_data(str![[r#" +... +[COMPILING] foo v0.0.1 ([ROOT]/home/.cargo/git/checkouts/foo-[HASH]/[..]) +... +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +... +"#]]) + .run(); + installed_process("foo") + .with_stdout_data(str![[r#" +onomatopoeia + +"#]]) + .run(); + // Check install stays fresh. + cargo_process("install --git") + .arg(git_project.url().to_string()) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/foo` +[IGNORED] package `foo v0.0.1 ([ROOTURL]/foo#[..])` is already installed, use --force to override +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn switch_sources() { + // Installing what appears to be the same thing, but from different + // sources should reinstall. + registry::alt_init(); + pkg("foo", "1.0.0"); + Package::new("foo", "1.0.0") + .file("src/main.rs", r#"fn main() { println!("alt"); }"#) + .alternative(true) + .publish(); + let p = project() + .at("foo-local") // so it doesn't use the same directory as the git project + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", r#"fn main() { println!("local"); }"#) + .build(); + let git_project = git::new("foo", |project| { + project.file("src/main.rs", r#"fn main() { println!("git"); }"#) + }); + + cargo_process("install foo").run(); + installed_process("foo") + .with_stdout_data(str![[r#" +1.0.0 + +"#]]) + .run(); + cargo_process("install foo --registry alternative").run(); + installed_process("foo") + .with_stdout_data(str![[r#" +alt + +"#]]) + .run(); + p.cargo("install --path .").run(); + installed_process("foo") + .with_stdout_data(str![[r#" +local + +"#]]) + .run(); + cargo_process("install --git") + .arg(git_project.url().to_string()) + .run(); + installed_process("foo") + .with_stdout_data(str![[r#" +git + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_report() { + // Testing the full output that indicates installed/ignored/replaced/summary. + pkg("one", "1.0.0"); + pkg("two", "1.0.0"); + fn three(vers: &str) { + Package::new("three", vers) + .file("src/main.rs", "fn main() { }") + .file("src/bin/x.rs", "fn main() { }") + .file("src/bin/y.rs", "fn main() { }") + .publish(); + } + three("1.0.0"); + cargo_process("install one two three") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] one v1.0.0 (registry `dummy-registry`) +[DOWNLOADING] crates ... +[DOWNLOADED] two v1.0.0 (registry `dummy-registry`) +[DOWNLOADING] crates ... +[DOWNLOADED] three v1.0.0 (registry `dummy-registry`) +[INSTALLING] one v1.0.0 +[COMPILING] one v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/one[EXE] +[INSTALLED] package `one v1.0.0` (executable `one[EXE]`) +[INSTALLING] two v1.0.0 +[COMPILING] two v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/two[EXE] +[INSTALLED] package `two v1.0.0` (executable `two[EXE]`) +[INSTALLING] three v1.0.0 +[COMPILING] three v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/three[EXE] +[INSTALLING] [ROOT]/home/.cargo/bin/x[EXE] +[INSTALLING] [ROOT]/home/.cargo/bin/y[EXE] +[INSTALLED] package `three v1.0.0` (executables `three[EXE]`, `x[EXE]`, `y[EXE]`) +[SUMMARY] Successfully installed one, two, three! +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + pkg("foo", "1.0.1"); + pkg("bar", "1.0.1"); + three("1.0.1"); + cargo_process("install one two three") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[IGNORED] package `one v1.0.0` is already installed, use --force to override +[IGNORED] package `two v1.0.0` is already installed, use --force to override +[DOWNLOADING] crates ... +[DOWNLOADED] three v1.0.1 (registry `dummy-registry`) +[INSTALLING] three v1.0.1 +[COMPILING] three v1.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/three[EXE] +[REPLACING] [ROOT]/home/.cargo/bin/x[EXE] +[REPLACING] [ROOT]/home/.cargo/bin/y[EXE] +[REPLACED] package `three v1.0.0` with `three v1.0.1` (executables `three[EXE]`, `x[EXE]`, `y[EXE]`) +[SUMMARY] Successfully installed one, two, three! +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + cargo_process("uninstall three") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/home/.cargo/bin/three[EXE] +[REMOVING] [ROOT]/home/.cargo/bin/x[EXE] +[REMOVING] [ROOT]/home/.cargo/bin/y[EXE] + +"#]]) + .run(); + cargo_process("install three --bin x") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[INSTALLING] three v1.0.1 +[COMPILING] three v1.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/x[EXE] +[INSTALLED] package `three v1.0.1` (executable `x[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + cargo_process("install three") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[INSTALLING] three v1.0.1 +[COMPILING] three v1.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/three[EXE] +[INSTALLING] [ROOT]/home/.cargo/bin/y[EXE] +[REPLACING] [ROOT]/home/.cargo/bin/x[EXE] +[INSTALLED] package `three v1.0.1` (executables `three[EXE]`, `y[EXE]`) +[REPLACED] package `three v1.0.1` with `three v1.0.1` (executable `x[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn no_track() { + pkg("foo", "1.0.0"); + cargo_process("install --no-track foo").run(); + assert!(!v1_path().exists()); + assert!(!v2_path().exists()); + cargo_process("install --no-track foo") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] binary `foo[EXE]` already exists in destination `[ROOT]/home/.cargo/bin/foo[EXE]` +Add --force to overwrite + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn deletes_orphaned() { + // When an executable is removed from a project, upgrading should remove it. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/bin/other.rs", "fn main() {}") + .file("examples/ex1.rs", "fn main() {}") + .build(); + p.cargo("install --path . --bins --examples").run(); + assert!(installed_exe("other").exists()); + + // Remove a binary, add a new one, and bump the version. + fs::remove_file(p.root().join("src/bin/other.rs")).unwrap(); + p.change_file("examples/ex2.rs", "fn main() {}"); + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.2.0" + "#, + ); + p.cargo("install --path . --bins --examples") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.2.0 ([ROOT]/foo) +[COMPILING] foo v0.2.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/ex2[EXE] +[REPLACING] [ROOT]/home/.cargo/bin/ex1[EXE] +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REMOVING] executable `[ROOT]/home/.cargo/bin/other[EXE]` from previous version foo v0.1.0 ([ROOT]/foo) +[INSTALLED] package `foo v0.2.0 ([ROOT]/foo)` (executable `ex2[EXE]`) +[REPLACED] package `foo v0.1.0 ([ROOT]/foo)` with `foo v0.2.0 ([ROOT]/foo)` (executables `ex1[EXE]`, `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + assert!(!installed_exe("other").exists()); + validate_trackers("foo", "0.2.0", &["foo", "ex1", "ex2"]); + // 0.1.0 should not have any entries. + validate_trackers("foo", "0.1.0", &[]); +} + +#[cargo_test] +fn already_installed_exact_does_not_update() { + pkg("foo", "1.0.0"); + cargo_process("install foo --version=1.0.0").run(); + cargo_process("install foo --version=1.0.0") + .with_stderr_data(str![[r#" +[IGNORED] package `foo v1.0.0` is already installed, use --force to override +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + cargo_process("install foo --version=>=1.0.0") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[IGNORED] package `foo v1.0.0` is already installed, use --force to override +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + pkg("foo", "1.0.1"); + cargo_process("install foo --version=>=1.0.0") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v1.0.1 (registry `dummy-registry`) +[INSTALLING] foo v1.0.1 +[COMPILING] foo v1.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v1.0.0` with `foo v1.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn already_installed_updates_yank_status_on_upgrade() { + pkg("foo", "1.0.0"); + pkg_maybe_yanked("foo", "1.0.1", true); + cargo_process("install foo --version=1.0.0").run(); + + cargo_process("install foo --version=1.0.1") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] cannot install package `foo`, it has been yanked from registry `crates-io` + +"#]]) + .run(); + + pkg_maybe_yanked("foo", "1.0.1", false); + + pkg("foo", "1.0.1"); + cargo_process("install foo --version=1.0.1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v1.0.1 (registry `dummy-registry`) +[INSTALLING] foo v1.0.1 +[COMPILING] foo v1.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v1.0.0` with `foo v1.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn partially_already_installed_does_one_update() { + pkg("foo", "1.0.0"); + cargo_process("install foo --version=1.0.0").run(); + pkg("bar", "1.0.0"); + pkg("baz", "1.0.0"); + cargo_process("install foo bar baz --version=1.0.0") + .with_stderr_data(str![[r#" +[IGNORED] package `foo v1.0.0` is already installed, use --force to override +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[DOWNLOADING] crates ... +[DOWNLOADED] baz v1.0.0 (registry `dummy-registry`) +[INSTALLING] bar v1.0.0 +[COMPILING] bar v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/bar[EXE] +[INSTALLED] package `bar v1.0.0` (executable `bar[EXE]`) +[INSTALLING] baz v1.0.0 +[COMPILING] baz v1.0.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/baz[EXE] +[INSTALLED] package `baz v1.0.0` (executable `baz[EXE]`) +[SUMMARY] Successfully installed foo, bar, baz! +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/jobserver.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/jobserver.rs new file mode 100644 index 000000000..360c894af --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/jobserver.rs @@ -0,0 +1,412 @@ +//! Tests for the jobserver protocol. + +use std::env; +use std::net::TcpListener; +use std::process::Command; +use std::thread; + +use cargo_test_support::basic_bin_manifest; +use cargo_test_support::cargo_exe; +use cargo_test_support::install::assert_has_installed_exe; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::{project, rustc_host, str}; +use cargo_util::is_ci; + +const EXE_CONTENT: &str = r#" +use std::env; + +fn main() { + let var = env::var("CARGO_MAKEFLAGS").expect("no jobserver from env"); + let arg = var.split(' ') + .find(|p| p.starts_with("--jobserver")) + .unwrap(); + let val = &arg[arg.find('=').unwrap() + 1..]; + validate(val); +} + +#[cfg(unix)] +fn validate(s: &str) { + use std::fs::{self, File}; + use std::io::*; + use std::os::unix::prelude::*; + + if let Some((r, w)) = s.split_once(',') { + // `--jobserver-auth=R,W` + unsafe { + let mut read = File::from_raw_fd(r.parse().unwrap()); + let mut write = File::from_raw_fd(w.parse().unwrap()); + + let mut buf = [0]; + assert_eq!(read.read(&mut buf).unwrap(), 1); + assert_eq!(write.write(&buf).unwrap(), 1); + } + } else { + // `--jobserver-auth=fifo:PATH` is the default since GNU Make 4.4 + let (_, path) = s.split_once(':').expect("fifo:PATH"); + assert!(fs::metadata(path).unwrap().file_type().is_fifo()); + } +} + +#[cfg(windows)] +fn validate(_: &str) { + // a little too complicated for a test... +} +"#; + +fn make_exe() -> &'static str { + if cfg!(windows) { + "mingw32-make" + } else if cfg!(target_os = "aix") { + "gmake" + } else { + "make" + } +} + +#[cargo_test] +fn jobserver_exists() { + let p = project() + .file("build.rs", EXE_CONTENT) + .file("src/lib.rs", "") + .build(); + + // Explicitly use `-j2` to ensure that there's eventually going to be a + // token to read from `validate` above, since running the build script + // itself consumes a token. + p.cargo("check -j2").run(); +} + +#[cargo_test] +fn external_subcommand_inherits_jobserver() { + let make = make_exe(); + if Command::new(make).arg("--version").output().is_err() { + return; + } + + let name = "cargo-jobserver-check"; + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "{name}" + version = "0.0.1" + "# + ), + ) + .file("src/main.rs", EXE_CONTENT) + .file( + "Makefile", + "\ +all: +\t+$(CARGO) jobserver-check +", + ) + .build(); + + p.cargo("install --path .").run(); + assert_has_installed_exe(paths::cargo_home(), name); + + p.process(make).env("CARGO", cargo_exe()).arg("-j2").run(); +} + +#[cargo_test] +fn runner_inherits_jobserver() { + let make = make_exe(); + if Command::new(make).arg("--version").output().is_err() { + return; + } + + let runner = "runner"; + project() + .at(runner) + .file("Cargo.toml", &basic_bin_manifest(runner)) + .file( + "src/main.rs", + r#" + pub fn main() { + eprintln!("this is a runner"); + let args: Vec = std::env::args().collect(); + let status = std::process::Command::new(&args[1]).status().unwrap(); + assert!(status.success()); + } + "#, + ) + .build() + .cargo("install --path .") + .run(); + + // Add .cargo/bin to PATH + let mut path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect(); + path.push(paths::cargo_home().join("bin")); + let path = &env::join_paths(path).unwrap(); + assert_has_installed_exe(paths::cargo_home(), runner); + + let host = rustc_host(); + let config_value = &format!("target.{host}.runner = \"{runner}\""); + + let name = "cargo-jobserver-check"; + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "{name}" + version = "0.0.1" + edition = "2015" + "# + ), + ) + .file( + "src/lib.rs", + r#" +#[test] +fn test() { + _ = std::env::var("CARGO_MAKEFLAGS").expect("no jobserver from env"); +} + "#, + ) + .file("src/main.rs", EXE_CONTENT) + .file( + "Makefile", + &format!( + "\ +run: +\t+$(CARGO) run + +run-runner: +\t+$(CARGO) run --config '{config_value}' + +test: +\t+$(CARGO) test --lib + +test-runner: +\t+$(CARGO) test --lib --config '{config_value}' +", + ), + ) + .build(); + + // jobserver can be inherited from env + p.process(make) + .env("CARGO", cargo_exe()) + .arg("run") + .arg("-j2") + .run(); + p.process(make) + .env("PATH", path) + .env("CARGO", cargo_exe()) + .arg("run-runner") + .arg("-j2") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `runner target/debug/cargo-jobserver-check[EXE]` +this is a runner + +"#]]) + .run(); + p.process(make) + .env("CARGO", cargo_exe()) + .arg("test") + .arg("-j2") + .run(); + p.process(make) + .env("PATH", path) + .env("CARGO", cargo_exe()) + .arg("test-runner") + .arg("-j2") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/cargo_jobserver_check-[HASH][EXE]) +this is a runner + +"#]]) + .run(); + + // but not from `-j` flag + p.cargo("run -j2") + .with_status(101) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/cargo-jobserver-check[EXE]` +... +[..]no jobserver from env[..] +... + +"#]]) + .run(); + p.cargo("run -j2") + .env("PATH", path) + .arg("--config") + .arg(config_value) + .with_status(101) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `runner target/debug/cargo-jobserver-check[EXE]` +this is a runner +... +[..]no jobserver from env[..] +... + +"#]]) + .run(); + p.cargo("test -j2") + .with_status(101) + .with_stdout_data("...\n[..]no jobserver from env[..]\n...") + .run(); + p.cargo("test -j2") + .env("PATH", path) + .arg("--config") + .arg(config_value) + .with_status(101) + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/cargo_jobserver_check-[HASH][EXE]) +this is a runner +... + +"#]]) + .with_stdout_data("...\n[..]no jobserver from env[..]\n...") + .run(); +} + +#[cargo_test] +fn makes_jobserver_used() { + let make = make_exe(); + if !is_ci() && Command::new(make).arg("--version").output().is_err() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + d1 = { path = "d1" } + d2 = { path = "d2" } + d3 = { path = "d3" } + "#, + ) + .file("src/lib.rs", "") + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + authors = [] + build = "../dbuild.rs" + "#, + ) + .file("d1/src/lib.rs", "") + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + authors = [] + build = "../dbuild.rs" + "#, + ) + .file("d2/src/lib.rs", "") + .file( + "d3/Cargo.toml", + r#" + [package] + name = "d3" + version = "0.0.1" + authors = [] + build = "../dbuild.rs" + "#, + ) + .file("d3/src/lib.rs", "") + .file( + "dbuild.rs", + r#" + use std::net::TcpStream; + use std::env; + use std::io::Read; + + fn main() { + let addr = env::var("ADDR").unwrap(); + let mut stream = TcpStream::connect(addr).unwrap(); + let mut v = Vec::new(); + stream.read_to_end(&mut v).unwrap(); + } + "#, + ) + .file( + "Makefile", + "\ +all: +\t+$(CARGO) build +", + ) + .build(); + + let l = TcpListener::bind("127.0.0.1:0").unwrap(); + let addr = l.local_addr().unwrap(); + + let child = thread::spawn(move || { + let a1 = l.accept().unwrap(); + let a2 = l.accept().unwrap(); + l.set_nonblocking(true).unwrap(); + + for _ in 0..1000 { + assert!(l.accept().is_err()); + thread::yield_now(); + } + + drop(a1); + l.set_nonblocking(false).unwrap(); + let a3 = l.accept().unwrap(); + + drop((a2, a3)); + }); + + p.process(make) + .env("CARGO", cargo_exe()) + .env("ADDR", addr.to_string()) + .arg("-j2") + .run(); + child.join().unwrap(); +} + +#[cargo_test] +fn jobserver_and_j() { + let make = make_exe(); + if !is_ci() && Command::new(make).arg("--version").output().is_err() { + return; + } + + let p = project() + .file("src/lib.rs", "") + .file( + "Makefile", + "\ +all: +\t+$(CARGO) build -j2 +", + ) + .build(); + + p.process(make) + .env("CARGO", cargo_exe()) + .arg("-j2") + .with_stderr_data(str![[r#" +[WARNING] a `-j` argument was passed to Cargo but Cargo is also configured with an external jobserver in its environment, ignoring the `-j` parameter +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/mod.rs new file mode 100644 index 000000000..bb4ff319a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{file, project}; + +#[cargo_test] +fn case() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true + +[lints.cargo] +im_a_teapot = "deny" + "#, + ) + .file("src/lib.rs", "") + .build(); + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"]) + .current_dir(p.root()) + .arg("check") + .arg("-Zcargo-lints") + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/stderr.term.svg new file mode 100644 index 000000000..ed03c725e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/error/stderr.term.svg @@ -0,0 +1,41 @@ + + + + + + + error: `im_a_teapot` is specified + + --> Cargo.toml:9:1 + + | + + 9 | im-a-teapot = true + + | ^^^^^^^^^^^^^^^^^^ + + | + + = note: `cargo::im_a_teapot` is set to `deny` in `[lints]` + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/mod.rs new file mode 100644 index 000000000..81f4ffc66 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/mod.rs @@ -0,0 +1,43 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{file, project}; + +#[cargo_test] +fn case() { + let p = project() + .file( + "Cargo.toml", + r#" +[workspace] +members = ["foo"] + +[workspace.lints.cargo] +im_a_teapot = { level = "warn", priority = 10 } +"#, + ) + .file( + "foo/Cargo.toml", + r#" +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] + +[lints] +workspace = true +"#, + ) + .file("foo/src/lib.rs", "") + .build(); + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["cargo-lints"]) + .current_dir(p.root()) + .arg("check") + .arg("-Zcargo-lints") + .assert() + .code(101) + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/stderr.term.svg new file mode 100644 index 000000000..9ef4f0c5b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/inherited/stderr.term.svg @@ -0,0 +1,57 @@ + + + + + + + error: use of unstable lint `im_a_teapot` + + --> Cargo.toml:6:1 + + | + + 6 | im_a_teapot = { level = "warn", priority = 10 } + + | ^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled + + | + + note: `cargo::im_a_teapot` was inherited + + --> foo/Cargo.toml:9:1 + + | + + 9 | workspace = true + + | ---------------- + + | + + = help: consider adding `cargo-features = ["test-dummy-unstable"]` to the top of the manifest + + error: encountered 1 errors(s) while verifying lints + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/mod.rs new file mode 100644 index 000000000..70dd35265 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/mod.rs @@ -0,0 +1,326 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +mod error; +mod inherited; +mod unknown_lints; +mod warning; + +#[cargo_test] +fn dashes_dont_get_rewritten() { + let foo = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true + +[lints.cargo] +im-a-teapot = "warn" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[WARNING] unknown lint: `im-a-teapot` + --> Cargo.toml:12:1 + | +12 | im-a-teapot = "warn" + | ^^^^^^^^^^^ + | + = [NOTE] `cargo::unknown_lints` is set to `warn` by default + = [HELP] there is a lint with a similar name: `im_a_teapot` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn forbid_not_overridden() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true + +[lints.cargo] +im_a_teapot = { level = "warn", priority = 10 } +test_dummy_unstable = { level = "forbid", priority = -1 } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `im_a_teapot` is specified + --> Cargo.toml:9:1 + | +9 | im-a-teapot = true + | ^^^^^^^^^^^^^^^^^^ + | + = [NOTE] `cargo::im_a_teapot` is set to `forbid` in `[lints]` + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_lints() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[workspace.lints.cargo] +im_a_teapot = { level = "warn", priority = 10 } +test_dummy_unstable = { level = "forbid", priority = -1 } + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true + +[lints] +workspace = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `im_a_teapot` is specified + --> Cargo.toml:13:1 + | +13 | im-a-teapot = true + | ^^^^^^^^^^^^^^^^^^ + | + = [NOTE] `cargo::im_a_teapot` is set to `forbid` in `[lints]` + +"#]]) + .run(); +} + +#[cargo_test] +fn dont_always_inherit_workspace_lints() { + let p = project() + .file( + "Cargo.toml", + r#" +[workspace] +members = ["foo"] + +[workspace.lints.cargo] +im_a_teapot = "warn" +"#, + ) + .file( + "foo/Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true +"#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cap_lints() { + Package::new("baz", "0.1.0").publish(); + Package::new("bar", "0.1.0") + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "bar" +version = "0.1.0" +edition = "2021" +im-a-teapot = true + +[dependencies] +baz = { version = "0.1.0", optional = true } + +[lints.cargo] +im_a_teapot = "warn" +"#, + ) + .file("src/lib.rs", "") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.1.0" +edition = "2021" + +[dependencies] +bar = "0.1.0" +"#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn check_feature_gated() { + let p = project() + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] + +[lints.cargo] +im_a_teapot = "warn" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] use of unstable lint `im_a_teapot` + --> Cargo.toml:9:1 + | +9 | im_a_teapot = "warn" + | ^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled + | + = [HELP] consider adding `cargo-features = ["test-dummy-unstable"]` to the top of the manifest +[ERROR] encountered 1 errors(s) while verifying lints + +"#]]) + .run(); +} + +#[cargo_test] +fn check_feature_gated_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" +[workspace] +members = ["foo"] + +[workspace.lints.cargo] +im_a_teapot = { level = "warn", priority = 10 } +test_dummy_unstable = { level = "forbid", priority = -1 } + "#, + ) + .file( + "foo/Cargo.toml", + r#" +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] + +[lints] +workspace = true + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] use of unstable lint `im_a_teapot` + --> Cargo.toml:6:1 + | +6 | im_a_teapot = { level = "warn", priority = 10 } + | ^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled + | +[NOTE] `cargo::im_a_teapot` was inherited + --> foo/Cargo.toml:9:1 + | +9 | workspace = true + | ---------------- + | + = [HELP] consider adding `cargo-features = ["test-dummy-unstable"]` to the top of the manifest +[ERROR] use of unstable lint `test_dummy_unstable` + --> Cargo.toml:7:1 + | +7 | test_dummy_unstable = { level = "forbid", priority = -1 } + | ^^^^^^^^^^^^^^^^^^^ this is behind `test-dummy-unstable`, which is not enabled + | +[NOTE] `cargo::test_dummy_unstable` was inherited + --> foo/Cargo.toml:9:1 + | +9 | workspace = true + | ---------------- + | + = [HELP] consider adding `cargo-features = ["test-dummy-unstable"]` to the top of the manifest +[ERROR] encountered 2 errors(s) while verifying lints + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/unknown_lints.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/unknown_lints.rs new file mode 100644 index 000000000..f8b3e9d6f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/unknown_lints.rs @@ -0,0 +1,91 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn default() { + let p = project() + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] + +[lints.cargo] +this-lint-does-not-exist = "warn" +"#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints"]) + .with_stderr_data(str![[r#" +[WARNING] unknown lint: `this-lint-does-not-exist` + --> Cargo.toml:9:1 + | +9 | this-lint-does-not-exist = "warn" + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = [NOTE] `cargo::unknown_lints` is set to `warn` by default +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn inherited() { + let p = project() + .file( + "Cargo.toml", + r#" +[workspace] +members = ["foo"] + +[workspace.lints.cargo] +this-lint-does-not-exist = "warn" +"#, + ) + .file( + "foo/Cargo.toml", + r#" +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] + +[lints] +workspace = true + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints"]) + .with_stderr_data(str![[r#" +[WARNING] unknown lint: `this-lint-does-not-exist` + --> Cargo.toml:6:1 + | +6 | this-lint-does-not-exist = "warn" + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +[NOTE] `cargo::this-lint-does-not-exist` was inherited + --> foo/Cargo.toml:9:1 + | +9 | workspace = true + | ---------------- + | + = [NOTE] `cargo::unknown_lints` is set to `warn` by default +[CHECKING] foo v0.0.1 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/mod.rs new file mode 100644 index 000000000..f1ec40f76 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{file, project}; + +#[cargo_test] +fn case() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true + +[lints.cargo] +im_a_teapot = "warn" + "#, + ) + .file("src/lib.rs", "") + .build(); + + snapbox::cmd::Command::cargo_ui() + .masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"]) + .current_dir(p.root()) + .arg("check") + .arg("-Zcargo-lints") + .assert() + .success() + .stdout_eq(str![""]) + .stderr_eq(file!["stderr.term.svg"]); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/stderr.term.svg b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/stderr.term.svg new file mode 100644 index 000000000..4ab424afa --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints/warning/stderr.term.svg @@ -0,0 +1,46 @@ + + + + + + + warning: `im_a_teapot` is specified + + --> Cargo.toml:9:1 + + | + + 9 | im-a-teapot = true + + | ------------------ + + | + + = note: `cargo::im_a_teapot` is set to `warn` in `[lints]` + + Checking foo v0.0.1 ([ROOT]/foo) + + Finished `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + + + + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints_table.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints_table.rs new file mode 100644 index 000000000..c2e232c50 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lints_table.rs @@ -0,0 +1,843 @@ +//! Tests for `[lints]` + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +#[cargo_test] +fn dependency_warning_ignored() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar.path = "../bar" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let _bar = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [lints.rust] + unsafe_code = "forbid" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.0.1 ([ROOT]/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn malformed_on_stable() { + let foo = project() + .file( + "Cargo.toml", + r#" + lints = 20 + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: integer `20`, expected a lints table + --> Cargo.toml:2:25 + | +2 | lints = 20 + | ^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn fail_on_invalid_tool() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace.lints.super-awesome-linter] + unsafe_code = "forbid" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check").with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: unrecognized lint tool `lints.super-awesome-linter`, specifying unrecognized tools may break in the future. +supported tools: cargo, clippy, rust, rustdoc +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn invalid_type_in_lint_value() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [workspace.lints.rust] + rust-2018-idioms = -1 + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: integer `-1`, expected a string or map + --> Cargo.toml:8:36 + | +8 | rust-2018-idioms = -1 + | ^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_on_unused_key() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [workspace.lints.rust] + rust-2018-idioms = { level = "allow", unused = true } + [lints.rust] + rust-2018-idioms = { level = "allow", unused = true } + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: `lints.rust.rust-2018-idioms.unused` +[WARNING] [ROOT]/foo/Cargo.toml: unused manifest key: `lints.rust.rust-2018-idioms.unused` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fail_on_tool_injection() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace.lints.rust] + "clippy::cyclomatic_complexity" = "warn" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `lints.rust.clippy::cyclomatic_complexity` is not valid lint name; try `lints.clippy.cyclomatic_complexity` + +"#]]) + .run(); +} + +#[cargo_test] +fn fail_on_redundant_tool() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace.lints.rust] + "rust::unsafe_code" = "forbid" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `lints.rust.rust::unsafe_code` is not valid lint name; try `lints.rust.unsafe_code` + +"#]]) + .run(); +} + +#[cargo_test] +fn fail_on_conflicting_tool() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace.lints.rust] + "super-awesome-tool::unsafe_code" = "forbid" + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `lints.rust.super-awesome-tool::unsafe_code` is not a valid lint name + +"#]]) + .run(); +} + +#[cargo_test] +fn package_lint_deny() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [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_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[ERROR] usage of an `unsafe` block +... +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_cant_be_false() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lints] + workspace = false + + [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_data(str![[r#" +[ERROR] `workspace` cannot be false + --> Cargo.toml:9:29 + | +9 | workspace = false + | ^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_lint_deny() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lints] + workspace = true + + [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_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[ERROR] usage of an `unsafe` block +... +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_and_package_lints() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + 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_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/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( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lints.rust] + "unsafe_code" = "deny" + "#, + ) + .file( + "src/lib.rs", + " +#![allow(unsafe_code)] + +pub fn foo(num: i32) -> u32 { + unsafe { std::mem::transmute(num) } +} +", + ) + .build(); + + foo.cargo("check") + .arg("-v") // Show order of rustflags on failure + .run(); +} + +#[cargo_test] +fn rustflags_has_precedence() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lints.rust] + "unsafe_code" = "deny" + "#, + ) + .file( + "src/lib.rs", + " +pub fn foo(num: i32) -> u32 { + unsafe { std::mem::transmute(num) } +} +", + ) + .build(); + + foo.cargo("check") + .arg("-v") // Show order of rustflags on failure + .env("RUSTFLAGS", "-Aunsafe_code") + .run(); +} + +#[cargo_test] +fn profile_rustflags_has_precedence() { + let foo = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["profile-rustflags"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [lints.rust] + "unsafe_code" = "deny" + + [profile.dev] + rustflags = ["-A", "unsafe_code"] + "#, + ) + .file( + "src/lib.rs", + " +pub fn foo(num: i32) -> u32 { + unsafe { std::mem::transmute(num) } +} +", + ) + .build(); + + foo.cargo("check") + .arg("-v") // Show order of rustflags on failure + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .run(); +} + +#[cargo_test] +fn build_rustflags_has_precedence() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [lints.rust] + "unsafe_code" = "deny" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["-A", "unsafe_code"] +"#, + ) + .file( + "src/lib.rs", + " +pub fn foo(num: i32) -> u32 { + unsafe { std::mem::transmute(num) } +} +", + ) + .build(); + + foo.cargo("check") + .arg("-v") // Show order of rustflags on failure + .run(); +} + +#[cargo_test] +fn without_priority() { + Package::new("reg-dep", "1.0.0").publish(); + + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2018" + authors = [] + + [dependencies] + reg-dep = "1.0.0" + + [lints.rust] + "rust-2018-idioms" = "deny" + "unused-extern-crates" = "allow" + "#, + ) + .file( + "src/lib.rs", + " +extern crate reg_dep; + +pub fn foo() -> u32 { + 2 +} +", + ) + .build(); + + foo.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] unused extern crate +... +"#]]) + .run(); +} + +#[cargo_test] +fn with_priority() { + Package::new("reg-dep", "1.0.0").publish(); + + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2018" + authors = [] + + [dependencies] + reg-dep = "1.0.0" + + [lints.rust] + "rust-2018-idioms" = { level = "deny", priority = -1 } + "unused-extern-crates" = "allow" + "#, + ) + .file( + "src/lib.rs", + " +extern crate reg_dep; + +pub fn foo() -> u32 { + 2 +} +", + ) + .build(); + + foo.cargo("check").run(); +} + +#[cargo_test] +fn rustdoc_lint() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lints.rustdoc] + broken_intra_doc_links = "deny" + "#, + ) + .file( + "src/lib.rs", + " +/// [`bar`] doesn't exist +pub fn foo() -> u32 { +} +", + ) + .build(); + + foo.cargo("doc") + .with_status(101) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[ERROR] unresolved link to `bar` +... +"#]]) + .run(); +} + +#[cargo_test] +fn doctest_respects_lints() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lints.rust] + confusable-idents = 'allow' + "#, + ) + .file( + "src/lib.rs", + r#" +/// Test +/// +/// [`Foo`] +/// +/// ``` +/// let s = "rust"; +/// let s_s = "rust2"; +/// ``` +pub fn f() {} +pub const Ě: i32 = 1; +pub const Ĕ: i32 = 2; +"#, + ) + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + foo.cargo("test --doc") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[DOCTEST] foo + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_lints_nightly_required() { + let foo = project() + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] + +[lints.cargo] + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] unused manifest key `lints.cargo` (may be supported in a future version) + +this Cargo does not support nightly features, but if you +switch to nightly channel you can pass +`-Zcargo-lints` to enable this feature. +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_lints_no_z_flag() { + let foo = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true + +[lints.cargo] + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[WARNING] unused manifest key `lints.cargo` (may be supported in a future version) + +consider passing `-Zcargo-lints` to enable this feature. +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_lints_success() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["test-dummy-unstable"] + +[package] +name = "foo" +version = "0.0.1" +edition = "2015" +authors = [] +im-a-teapot = true + +[lints.cargo] +im_a_teapot = "warn" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -Zcargo-lints") + .masquerade_as_nightly_cargo(&["cargo-lints", "test-dummy-unstable"]) + .with_stderr_data(str![[r#" +[WARNING] `im_a_teapot` is specified + --> Cargo.toml:9:1 + | +9 | im-a-teapot = true + | ------------------ + | + = [NOTE] `cargo::im_a_teapot` is set to `warn` in `[lints]` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/list_availables.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/list_availables.rs new file mode 100644 index 000000000..a2aa80e9a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/list_availables.rs @@ -0,0 +1,1005 @@ +//! Tests for packages/target filter flags giving suggestions on which +//! packages/targets are available. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; +use snapbox::IntoData; + +fn list_availables_test(command: &str, expected: ExpectedSnapshots) { + let full_project = project() + .file("examples/a.rs", "fn main() { }") + .file("examples/b.rs", "fn main() { }") + .file("benches/bench1.rs", "") + .file("benches/bench2.rs", "") + .file("tests/test1.rs", "") + .file("tests/test2.rs", "") + .file("src/main.rs", "fn main() { }") + .file("Cargo.lock", "") // for `cargo pkgid` + .build(); + + if let ExpectedSnapshots { + example: ProjectExpected { + full: Some(example), + .. + }, + .. + } = expected + { + full_project + .cargo(&format!("{} --example", command)) + .with_stderr_data(example) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + bin: ProjectExpected { + full: Some(bin), .. + }, + .. + } = expected + { + full_project + .cargo(&format!("{} --bin", command)) + .with_stderr_data(bin) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + bench: ProjectExpected { + full: Some(bench), .. + }, + .. + } = expected + { + full_project + .cargo(&format!("{} --bench", command)) + .with_stderr_data(bench) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + test: ProjectExpected { + full: Some(test), .. + }, + .. + } = expected + { + full_project + .cargo(&format!("{} --test", command)) + .with_stderr_data(test) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + package: ProjectExpected { + full: Some(package), + .. + }, + .. + } = expected + { + full_project + .cargo(&format!("{} -p", command)) + .with_stderr_data(package) + .with_status(101) + .run(); + } + + let empty_project = project().file("src/lib.rs", "").build(); + + if let ExpectedSnapshots { + example: ProjectExpected { + empty: Some(example), + .. + }, + .. + } = expected + { + empty_project + .cargo(&format!("{} --example", command)) + .with_stderr_data(example) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + bin: ProjectExpected { + empty: Some(bin), .. + }, + .. + } = expected + { + empty_project + .cargo(&format!("{} --bin", command)) + .with_stderr_data(bin) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + bench: ProjectExpected { + empty: Some(bench), .. + }, + .. + } = expected + { + empty_project + .cargo(&format!("{} --bench", command)) + .with_stderr_data(bench) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + test: ProjectExpected { + empty: Some(test), .. + }, + .. + } = expected + { + empty_project + .cargo(&format!("{} --test", command)) + .with_stderr_data(test) + .with_status(101) + .run(); + } + + if let ExpectedSnapshots { + target: ProjectExpected { + empty: Some(target), + .. + }, + .. + } = expected + { + empty_project + .cargo(&format!("{} --target", command)) + .with_stderr_data(target) + .with_status(101) + .run(); + } +} + +#[cargo_test] +fn build_list_availables() { + list_availables_test( + "build", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_test(str![[r#" +[ERROR] "--test" takes one argument. +Available test targets: + test1 + test2 + + +"#]], str![[r#" +[ERROR] "--test" takes one argument. +No test targets available. + + +"#]]) + .with_bench(str![[r#" +[ERROR] "--bench" takes one argument. +Available bench targets: + bench1 + bench2 + + +"#]], str![[r#" +[ERROR] "--bench" takes one argument. +No bench targets available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn check_list_availables() { + list_availables_test( + "check", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_test(str![[r#" +[ERROR] "--test" takes one argument. +Available test targets: + test1 + test2 + + +"#]], str![[r#" +[ERROR] "--test" takes one argument. +No test targets available. + + +"#]]) + .with_bench(str![[r#" +[ERROR] "--bench" takes one argument. +Available bench targets: + bench1 + bench2 + + +"#]], str![[r#" +[ERROR] "--bench" takes one argument. +No bench targets available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn doc_list_availables() { + list_availables_test( + "doc", + SnapshotsBuilder::new() + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn fix_list_availables() { + list_availables_test( + "fix", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_test(str![[r#" +[ERROR] "--test" takes one argument. +Available test targets: + test1 + test2 + + +"#]], str![[r#" +[ERROR] "--test" takes one argument. +No test targets available. + + +"#]]) + .with_bench(str![[r#" +[ERROR] "--bench" takes one argument. +Available bench targets: + bench1 + bench2 + + +"#]], str![[r#" +[ERROR] "--bench" takes one argument. +No bench targets available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn run_list_availables() { + list_availables_test( + "run", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn test_list_availables() { + list_availables_test( + "test", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_test(str![[r#" +[ERROR] "--test" takes one argument. +Available test targets: + test1 + test2 + + +"#]], str![[r#" +[ERROR] "--test" takes one argument. +No test targets available. + + +"#]]) + .with_bench(str![[r#" +[ERROR] "--bench" takes one argument. +Available bench targets: + bench1 + bench2 + + +"#]], str![[r#" +[ERROR] "--bench" takes one argument. +No bench targets available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn bench_list_availables() { + list_availables_test( + "bench", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_test(str![[r#" +[ERROR] "--test" takes one argument. +Available test targets: + test1 + test2 + + +"#]], str![[r#" +[ERROR] "--test" takes one argument. +No test targets available. + + +"#]]) + .with_bench(str![[r#" +[ERROR] "--bench" takes one argument. +Available bench targets: + bench1 + bench2 + + +"#]], str![[r#" +[ERROR] "--bench" takes one argument. +No bench targets available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn install_list_availables() { + list_availables_test( + "install", + SnapshotsBuilder::new() + .with_example( + str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], + str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]], + ) + .with_bin( + str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], + str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]], + ) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn rustdoc_list_availables() { + list_availables_test( + "rustdoc", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_test(str![[r#" +[ERROR] "--test" takes one argument. +Available test targets: + test1 + test2 + + +"#]], str![[r#" +[ERROR] "--test" takes one argument. +No test targets available. + + +"#]]) + .with_bench(str![[r#" +[ERROR] "--bench" takes one argument. +Available bench targets: + bench1 + bench2 + + +"#]], str![[r#" +[ERROR] "--bench" takes one argument. +No bench targets available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn rustc_list_availables() { + list_availables_test( + "rustc", + SnapshotsBuilder::new() + .with_example(str![[r#" +[ERROR] "--example" takes one argument. +Available examples: + a + b + + +"#]], str![[r#" +[ERROR] "--example" takes one argument. +No examples available. + + +"#]]) + .with_bin(str![[r#" +[ERROR] "--bin" takes one argument. +Available binaries: + foo + + +"#]], str![[r#" +[ERROR] "--bin" takes one argument. +No binaries available. + + +"#]]) + .with_test(str![[r#" +[ERROR] "--test" takes one argument. +Available test targets: + test1 + test2 + + +"#]], str![[r#" +[ERROR] "--test" takes one argument. +No test targets available. + + +"#]]) + .with_bench(str![[r#" +[ERROR] "--bench" takes one argument. +Available bench targets: + bench1 + bench2 + + +"#]], str![[r#" +[ERROR] "--bench" takes one argument. +No bench targets available. + + +"#]]) + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn pkgid_list_availables() { + list_availables_test( + "pkgid", + SnapshotsBuilder::new() + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn tree_list_availables() { + list_availables_test( + "tree", + SnapshotsBuilder::new() + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ) +} + +#[cargo_test] +fn clean_list_availables() { + list_availables_test( + "clean", + SnapshotsBuilder::new() + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .with_target(str![[r#" +[ERROR] "--target" takes a target architecture as an argument. + +Run `[..]` to see possible targets. + +"#]]) + .build(), + ); +} + +#[cargo_test] +fn update_list_availables() { + list_availables_test( + "update", + SnapshotsBuilder::new() + .with_package(str![[r#" +[ERROR] "--package " requires a SPEC format value, which can be any package ID specifier in the dependency graph. +Run `cargo help pkgid` for more information about SPEC format. + +Possible packages/workspace members: + foo + + +"#]]) + .build(), + ); +} + +struct ExpectedSnapshots { + example: ProjectExpected, + bin: ProjectExpected, + test: ProjectExpected, + bench: ProjectExpected, + package: ProjectExpected, + target: ProjectExpected, +} + +struct ProjectExpected { + full: Option, + empty: Option, +} + +struct SnapshotsBuilder { + example: ProjectExpected, + bin: ProjectExpected, + test: ProjectExpected, + bench: ProjectExpected, + package: ProjectExpected, + target: ProjectExpected, +} + +impl SnapshotsBuilder { + pub fn new() -> Self { + Self { + example: ProjectExpected { + full: None, + empty: None, + }, + bin: ProjectExpected { + full: None, + empty: None, + }, + test: ProjectExpected { + full: None, + empty: None, + }, + bench: ProjectExpected { + full: None, + empty: None, + }, + package: ProjectExpected { + full: None, + empty: None, + }, + target: ProjectExpected { + full: None, + empty: None, + }, + } + } + + fn with_example(mut self, full: T, empty: T) -> Self { + self.example.full = Some(full); + self.example.empty = Some(empty); + self + } + + fn with_bin(mut self, full: T, empty: T) -> Self { + self.bin.full = Some(full); + self.bin.empty = Some(empty); + self + } + + fn with_test(mut self, full: T, empty: T) -> Self { + self.test.full = Some(full); + self.test.empty = Some(empty); + self + } + + fn with_bench(mut self, full: T, empty: T) -> Self { + self.bench.full = Some(full); + self.bench.empty = Some(empty); + self + } + + fn with_package(mut self, full: T) -> Self { + self.package.full = Some(full); + self + } + + fn with_target(mut self, empty: T) -> Self { + self.target.empty = Some(empty); + self + } + + fn build(self) -> ExpectedSnapshots { + ExpectedSnapshots { + example: self.example, + bin: self.bin, + test: self.test, + bench: self.bench, + package: self.package, + target: self.target, + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/local_registry.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/local_registry.rs new file mode 100644 index 000000000..a5ddcb48d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/local_registry.rs @@ -0,0 +1,554 @@ +//! Tests for local-registry sources. + +use std::fs; + +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{registry_path, Package}; +use cargo_test_support::{basic_manifest, project, str, t}; + +fn setup() { + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config.toml"), + r#" + [source.crates-io] + registry = 'https://wut' + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + local-registry = 'registry' + "# + )); +} + +#[cargo_test] +fn simple() { + setup(); + Package::new("bar", "0.0.1") + .local(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.0.1" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`) +[COMPILING] bar v0.0.1 +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("test").run(); +} + +#[cargo_test] +fn not_found() { + setup(); + // Publish a package so that the directory hierarchy is created. + // Note, however, that we declare a dependency on baZ. + Package::new("bar", "0.0.1").local(true).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.0.1" + "#, + ) + .file( + "src/lib.rs", + "extern crate baz; pub fn foo() { baz::bar(); }", + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no matching package named `baz` found +location searched: `[ROOT]/registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +fn depend_on_yanked() { + setup(); + Package::new("bar", "0.0.1").local(true).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Run cargo to create lock file. + p.cargo("check").run(); + + registry_path().join("index").join("3").rm_rf(); + Package::new("bar", "0.0.1") + .local(true) + .yanked(true) + .publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_versions() { + setup(); + Package::new("bar", "0.0.1").local(true).publish(); + Package::new("bar", "0.1.0") + .local(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[UNPACKING] bar v0.1.0 (registry `[ROOT]/registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + Package::new("bar", "0.2.0") + .local(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + + p.cargo("update") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.1.0 -> v0.2.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_names() { + setup(); + Package::new("bar", "0.0.1") + .local(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + Package::new("baz", "0.1.0") + .local(true) + .file("src/lib.rs", "pub fn baz() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + baz = "*" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + extern crate baz; + pub fn foo() { + bar::bar(); + baz::baz(); + } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`) +[UNPACKING] baz v0.1.0 (registry `[ROOT]/registry`) +[CHECKING] bar v0.0.1 +[CHECKING] baz v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn interdependent() { + setup(); + Package::new("bar", "0.0.1") + .local(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + Package::new("baz", "0.1.0") + .local(true) + .dep("bar", "*") + .file("src/lib.rs", "extern crate bar; pub fn baz() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + baz = "*" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + extern crate baz; + pub fn foo() { + bar::bar(); + baz::baz(); + } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`) +[UNPACKING] baz v0.1.0 (registry `[ROOT]/registry`) +[CHECKING] bar v0.0.1 +[CHECKING] baz v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn path_dep_rewritten() { + setup(); + Package::new("bar", "0.0.1") + .local(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + Package::new("baz", "0.1.0") + .local(true) + .dep("bar", "*") + .file( + "Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar", version = "*" } + "#, + ) + .file("src/lib.rs", "extern crate bar; pub fn baz() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + baz = "*" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + extern crate baz; + pub fn foo() { + bar::bar(); + baz::baz(); + } + "#, + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`) +[UNPACKING] baz v0.1.0 (registry `[ROOT]/registry`) +[CHECKING] bar v0.0.1 +[CHECKING] baz v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_dir_bad() { + setup(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [source.crates-io] + registry = 'https://wut' + replace-with = 'my-awesome-local-directory' + + [source.my-awesome-local-directory] + local-registry = '/path/to/nowhere' + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update registry `crates-io` + +Caused by: + failed to update replaced source registry `crates-io` + +Caused by: + local registry path is not a directory: [..]path[..]to[..]nowhere + +"#]]) + .run(); +} + +#[cargo_test] +fn different_directory_replacing_the_registry_is_bad() { + setup(); + + // Move our test's .cargo/config to a temporary location and publish a + // registry package we're going to use first. + let config = paths::root().join(".cargo"); + let config_tmp = paths::root().join(".cargo-old"); + t!(fs::rename(&config, &config_tmp)); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Generate a lock file against the crates.io registry + Package::new("bar", "0.0.1").publish(); + p.cargo("check").run(); + + // Switch back to our directory source, and now that we're replacing + // crates.io make sure that this fails because we're replacing with a + // different checksum + config.rm_rf(); + t!(fs::rename(&config_tmp, &config)); + Package::new("bar", "0.0.1") + .file("src/lib.rs", "invalid") + .local(true) + .publish(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] checksum for `bar v0.0.1` changed between lock files + +this could be indicative of a few possible errors: + + * the lock file is corrupt + * a replacement source in use (e.g., a mirror) returned a different checksum + * the source itself may be corrupt in one way or another + +unable to verify that `bar v0.0.1` is the same as when the lockfile was generated + + +"#]]) + .run(); +} + +#[cargo_test] +fn crates_io_registry_url_is_optional() { + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write( + root.join(".cargo/config.toml"), + r#" + [source.crates-io] + replace-with = 'my-awesome-local-registry' + + [source.my-awesome-local-registry] + local-registry = 'registry' + "# + )); + + Package::new("bar", "0.0.1") + .local(true) + .file("src/lib.rs", "pub fn bar() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.0.1" + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[UNPACKING] bar v0.0.1 (registry `[ROOT]/registry`) +[COMPILING] bar v0.0.1 +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("test").run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/locate_project.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/locate_project.rs new file mode 100644 index 000000000..c6d91a30a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/locate_project.rs @@ -0,0 +1,125 @@ +//! Tests for the `cargo locate-project` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn simple() { + let p = project().build(); + + p.cargo("locate-project") + .with_stdout_data( + str![[r#" +{ + "root": "[ROOT]/foo/Cargo.toml" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn message_format() { + let p = project().build(); + + p.cargo("locate-project --message-format plain") + .with_stdout_data(str![[r#" +[ROOT]/foo/Cargo.toml + +"#]]) + .run(); + + p.cargo("locate-project --message-format json") + .with_stdout_data( + str![[r#" +{ + "root": "[ROOT]/foo/Cargo.toml" +} +"#]] + .is_json(), + ) + .run(); + + p.cargo("locate-project --message-format cryptic") + .with_stderr_data(str![[r#" +[ERROR] invalid message format specifier: `cryptic` + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "outer" + version = "0.0.0" + + [workspace] + members = ["inner"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "inner/Cargo.toml", + r#" + [package] + name = "inner" + version = "0.0.0" + "#, + ) + .file("inner/src/lib.rs", "") + .build(); + + p.cargo("locate-project") + .with_stdout_data( + str![[r#" +{ + "root": "[ROOT]/foo/Cargo.toml" +} +"#]] + .is_json(), + ) + .run(); + + p.cargo("locate-project") + .cwd("inner") + .with_stdout_data( + str![[r#" +{ + "root": "[ROOT]/foo/inner/Cargo.toml" +} +"#]] + .is_json(), + ) + .run(); + + p.cargo("locate-project --workspace") + .with_stdout_data( + str![[r#" +{ + "root": "[ROOT]/foo/Cargo.toml" +} +"#]] + .is_json(), + ) + .run(); + + p.cargo("locate-project --workspace") + .cwd("inner") + .with_stdout_data( + str![[r#" +{ + "root": "[ROOT]/foo/Cargo.toml" +} +"#]] + .is_json(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_compat.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_compat.rs new file mode 100644 index 000000000..4a24993b1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_compat.rs @@ -0,0 +1,1311 @@ +//! Tests for supporting older versions of the Cargo.lock file format. + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::git; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_lib_manifest, basic_manifest, project}; + +#[cargo_test] +fn oldest_lockfile_still_works() { + let cargo_commands = vec!["build", "update"]; + for cargo_command in cargo_commands { + oldest_lockfile_still_works_with_command(cargo_command); + } +} + +fn oldest_lockfile_still_works_with_command(cargo_command: &str) { + Package::new("bar", "0.1.0").publish(); + + let expected_lockfile = str![[r##" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] + +"##]]; + + let old_lockfile = r#" +[root] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +"#; + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("Cargo.lock", old_lockfile) + .build(); + + p.cargo(cargo_command).run(); + + let lock = p.read_lockfile(); + assert_e2e().eq(&lock, expected_lockfile); +} + +#[cargo_test] +fn frozen_flag_preserves_old_lockfile() { + let cksum = Package::new("bar", "0.1.0").publish(); + + let old_lockfile = format!( + r#"[root] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{}" +"#, + cksum, + ); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("Cargo.lock", &old_lockfile) + .build(); + + p.cargo("check --locked").run(); + + let lock = p.read_lockfile(); + assert_e2e().eq(&lock, &old_lockfile); +} + +#[cargo_test] +fn totally_wild_checksums_works() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "Cargo.lock", + r#" +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum baz 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum" +"checksum bar 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum" +"#, + ); + + let p = p.build(); + + p.cargo("check").run(); + + let lock = p.read_lockfile(); + assert_e2e().eq( + &lock, + str![[r##" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] + +"##]], + ); +} + +#[cargo_test] +fn wrong_checksum_is_an_error() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "Cargo.lock", + r#" +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "checksum" +"#, + ); + + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] checksum for `bar v0.1.0` changed between lock files + +this could be indicative of a few possible errors: + + * the lock file is corrupt + * a replacement source in use (e.g., a mirror) returned a different checksum + * the source itself may be corrupt in one way or another + +unable to verify that `bar v0.1.0` is the same as when the lockfile was generated + + +"#]]) + .run(); +} + +// If the checksum is unlisted in the lock file (e.g., ) yet we can +// calculate it (e.g., it's a registry dep), then we should in theory just fill +// it in. +#[cargo_test] +fn unlisted_checksum_is_bad_if_we_calculate() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "Cargo.lock", + r#" +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "" +"#, + ); + let p = p.build(); + + p.cargo("fetch").with_status(101).with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] checksum for `bar v0.1.0` was not previously calculated, but a checksum could now be calculated + +this could be indicative of a few possible situations: + + * the source `registry `crates-io`` did not previously support checksums, + but was replaced with one that does + * newer Cargo implementations know how to checksum this source, but this + older implementation does not + * the lock file is corrupt + + +"#]]).run(); +} + +// If the checksum is listed in the lock file yet we cannot calculate it (e.g., +// Git dependencies as of today), then make sure we choke. +#[cargo_test] +fn listed_checksum_bad_if_we_cannot_compute() { + let git = git::new("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .file( + "Cargo.lock", + &format!( + r#" +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (git+{0})" +] + +[[package]] +name = "bar" +version = "0.1.0" +source = "git+{0}" + +[metadata] +"checksum bar 0.1.0 (git+{0})" = "checksum" +"#, + git.url() + ), + ); + + let p = p.build(); + + p.cargo("fetch").with_status(101).with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[ERROR] checksum for `bar v0.1.0 ([ROOTURL]/bar)` could not be calculated, but a checksum is listed in the existing lock file + +this could be indicative of a few possible situations: + + * the source `[ROOTURL]/bar` supports checksums, + but was replaced with one that doesn't + * the lock file is corrupt + +unable to verify that `bar v0.1.0 ([ROOTURL]/bar)` is the same as when the lockfile was generated + + +"#]]).run(); +} + +#[cargo_test] +fn current_lockfile_format() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", ""); + let p = p.build(); + + p.cargo("check").run(); + + let actual = p.read_lockfile(); + + let expected = str![[r##" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] + +"##]]; + assert_e2e().eq(&actual, expected); +} + +#[cargo_test] +fn lockfile_without_root() { + Package::new("bar", "0.1.0").publish(); + + let lockfile = r#" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] +"#; + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("Cargo.lock", lockfile); + + let p = p.build(); + + p.cargo("check").run(); + + let lock = p.read_lockfile(); + assert_e2e().eq( + &lock, + str![[r##" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] + +"##]], + ); +} + +#[cargo_test] +fn locked_correct_error() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", ""); + let p = p.build(); + + p.cargo("check --locked") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] the lock file [ROOT]/foo/Cargo.lock needs to be updated but --locked was passed to prevent this +If you want to try to generate the lock file without accessing the network, remove the --locked flag and use --offline instead. + +"#]]) + .run(); +} + +#[cargo_test] +fn v2_format_preserved() { + let cksum = Package::new("bar", "0.1.0").publish(); + + let lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "{}" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] +"#, + cksum + ); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("Cargo.lock", &lockfile) + .build(); + + p.cargo("fetch").run(); + + let lock = p.read_lockfile(); + assert_e2e().eq(&lock, &lockfile); +} + +#[cargo_test] +fn v2_path_and_crates_io() { + let cksum010 = Package::new("a", "0.1.0").publish(); + let cksum020 = Package::new("a", "0.2.0").publish(); + + let lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "a" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "{}" + +[[package]] +name = "a" +version = "0.2.0" + +[[package]] +name = "a" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "{}" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "a 0.1.0", + "a 0.2.0", + "a 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] +"#, + cksum010, cksum020, + ); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = 'a' } + b = { version = "0.1", package = 'a' } + c = { version = "0.2", package = 'a' } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.2.0" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .file("Cargo.lock", &lockfile) + .build(); + + p.cargo("fetch").run(); + p.cargo("fetch").run(); + + let lock = p.read_lockfile(); + assert_e2e().eq(&lock, &lockfile); +} + +#[cargo_test] +fn v3_and_git() { + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + let head_id = repo.head().unwrap().target().unwrap(); + + let lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "dep1" +version = "0.5.0" +source = "git+[ROOTURL]/dep1?branch=master#{}" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "dep1", +] +"#, + head_id, + ); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + rust-version = "1.81" # ensure it stays in lockfile v3 + + [dependencies] + dep1 = {{ git = '{}', branch = 'master' }} + "#, + git_project.url(), + ), + ) + .file("src/lib.rs", "") + .file("Cargo.lock", "version = 3") + .build(); + + p.cargo("fetch").run(); + + let lock = p.read_lockfile(); + assert_e2e().eq(&lock, &lockfile); +} + +#[cargo_test] +fn lock_from_the_future() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .file("Cargo.lock", "version = 10000000") + .build(); + + p.cargo("fetch").with_stderr_data(str![[r#" +[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock + +Caused by: + lock file version `10000000` was found, but this version of Cargo does not understand this lock file, perhaps Cargo needs to be updated? + +"#]]).with_status(101).run(); +} + +#[cargo_test] +fn preserve_old_format_if_no_update_needed() { + let cksum = Package::new("bar", "0.1.0").publish(); + let lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{}" +"#, + cksum + ); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("Cargo.lock", &lockfile) + .build(); + + p.cargo("check --locked").run(); +} + +#[cargo_test] +fn same_name_version_different_sources() { + let cksum = Package::new("foo", "0.1.0").publish(); + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + }); + let head_id = repo.head().unwrap().target().unwrap(); + + // Lockfile was generated with Rust 1.51 + let lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "foo 0.1.0 (git+{url})", +] + +[[package]] +name = "foo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "{cksum}" + +[[package]] +name = "foo" +version = "0.1.0" +source = "git+{url}#{sha}" +"#, + sha = head_id, + url = git_project.url(), + cksum = cksum + ); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + foo = "0.1.0" + foo2 = {{ git = '{}', package = 'foo' }} + "#, + git_project.url(), + ), + ) + .file("src/lib.rs", "") + .file("Cargo.lock", &lockfile) + .build(); + + p.cargo("check").run(); + + assert_eq!(p.read_file("Cargo.lock"), lockfile); +} + +#[cargo_test] +fn bad_data_in_lockfile_error_meg() { + Package::new("bar", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "Cargo.lock", + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1b9346248cf3391ead604c4407258d327c28e37209f6d56127598165165dda" + +[[package]] +name = "test" +version = "0.0.0" +dependencies = [ + "bar", +]"#, + ) + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "*"` (locked to 0.1.0) +candidate versions found which didn't match: 0.0.1 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `test v0.0.0 ([ROOT]/foo)` +perhaps a crate was updated and forgotten to be re-vendored? + +"#]]) + .run(); +} + +#[cargo_test] +fn next_version_is_always_unstable() { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ), + ) + .file("src/lib.rs", "") + .file("Cargo.lock", "version = 5") + .build(); + + p.cargo("fetch").with_status(101).with_stderr_data(str![[r#" +[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock + +Caused by: + lock file version `5` was found, but this version of Cargo does not understand this lock file, perhaps Cargo needs to be updated? + +"#]]).run(); + + // On nightly, let the user know about the `-Z` flag. + p.cargo("fetch") + .masquerade_as_nightly_cargo(&["-Znext-lockfile-bump"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock + +Caused by: + lock file version `5` requires `-Znext-lockfile-bump` + +"#]]) + .run(); +} + +fn create_branch(repo: &git2::Repository, branch: &str, head_id: git2::Oid) { + repo.branch(branch, &repo.find_commit(head_id).unwrap(), true) + .unwrap(); +} + +fn create_tag(repo: &git2::Repository, tag: &str, head_id: git2::Oid) { + repo.tag( + tag, + &repo.find_object(head_id, None).unwrap(), + &repo.signature().unwrap(), + "make a new tag", + false, + ) + .unwrap(); +} + +fn v3_and_git_url_encoded(ref_kind: &str, f: impl FnOnce(&git2::Repository, &str, git2::Oid)) { + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + let url = git_project.url(); + let head_id = repo.head().unwrap().target().unwrap(); + // Ref name with special characters + let git_ref = "a-_+#$)"; + let encoded_ref = "a-_%2B%23%24%29"; + f(&repo, git_ref, head_id); + + let lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "dep1" +version = "0.5.0" +source = "git+[ROOTURL]/dep1?{ref_kind}={git_ref}#{head_id}" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "dep1", +] +"#, + ); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + rust-version = "1.81" # ensure it stays in lockfile v3 + + [dependencies] + dep1 = {{ git = '{url}', {ref_kind} = '{git_ref}' }} + "#, + ), + ) + .file("src/lib.rs", "") + .file("Cargo.lock", "version = 3") + .build(); + + p.cargo("check") + .with_stderr_data(format!( + "\ +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[ADDING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..]) +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +" + )) + .run(); + + let lock = p.read_lockfile(); + assert_e2e().eq(&lock, &lockfile); + + // v3 doesn't URL-encode URL parameters, but `url` crate does decode as it + // was URL-encoded. Therefore Cargo thinks they are from different source + // and clones the repository again. + p.cargo("check") + .with_stderr_data(format!( + "\ +[UPDATING] git repository `[ROOTURL]/dep1` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +" + )) + .run(); +} + +#[cargo_test] +fn v3_and_git_url_encoded_branch() { + v3_and_git_url_encoded("branch", create_branch); +} + +#[cargo_test] +fn v3_and_git_url_encoded_tag() { + v3_and_git_url_encoded("tag", create_tag); +} + +#[cargo_test] +fn v3_and_git_url_encoded_rev() { + v3_and_git_url_encoded("rev", create_tag); +} + +fn v4_and_git_url_encoded(ref_kind: &str, f: impl FnOnce(&git2::Repository, &str, git2::Oid)) { + let (git_project, repo) = git::new_repo("dep1", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("dep1")) + .file("src/lib.rs", "") + }); + let url = git_project.url(); + let head_id = repo.head().unwrap().target().unwrap(); + // Ref name with special characters + let git_ref = "a-_+#$)"; + let encoded_ref = "a-_%2B%23%24%29"; + f(&repo, git_ref, head_id); + + let lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "dep1" +version = "0.5.0" +source = "git+[ROOTURL]/dep1?{ref_kind}={encoded_ref}#{head_id}" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "dep1", +] +"#, + ); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + dep1 = {{ git = '{url}', {ref_kind} = '{git_ref}' }} + "#, + ), + ) + .file("src/lib.rs", "") + .file("Cargo.lock", "version = 4") + .build(); + + p.cargo("check") + .with_stderr_data(format!( + "\ +[UPDATING] git repository `[ROOTURL]/dep1` +[LOCKING] 1 package to latest compatible version +[ADDING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..]) +[CHECKING] dep1 v0.5.0 ([ROOTURL]/dep1?{ref_kind}={encoded_ref}#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +" + )) + .run(); + + let lock = p.read_lockfile(); + assert_e2e().eq(&lock, &lockfile); + + // Unlike v3_and_git_url_encoded, v4 encodes URL parameters so no git + // repository re-clone happen. + p.cargo("check") + .with_stderr_data( + "\ +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + ) + .run(); +} + +#[cargo_test] +fn v4_and_git_url_encoded_branch() { + v4_and_git_url_encoded("branch", create_branch); +} + +#[cargo_test] +fn v4_and_git_url_encoded_tag() { + v4_and_git_url_encoded("tag", create_tag); +} + +#[cargo_test] +fn v4_and_git_url_encoded_rev() { + v4_and_git_url_encoded("rev", create_tag) +} + +#[cargo_test] +fn with_msrv() { + let cksum = Package::new("bar", "0.1.0").publish(); + + let v3_lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "{cksum}" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] +"# + ); + let v2_lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "{cksum}" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar", +] +"# + ); + + let v1_lockfile = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.0.1" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{cksum}" +"# + ); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let cases = [ + // v1 is the default + ("1.37", None, 1), + ("1.37", Some(1), 1), + ("1.37", Some(2), 2), + ("1.37", Some(3), 3), + ("1.37", Some(4), 4), + // v2 introduced + ("1.38", None, 1), + // last version of v1 as the default + ("1.40", None, 1), + // v2 is the default + ("1.41", None, 2), + ("1.41", Some(1), 1), + ("1.41", Some(2), 2), + ("1.41", Some(3), 3), + ("1.41", Some(4), 4), + // v3 introduced + ("1.47", None, 2), + // last version of v2 as the default + ("1.48", None, 2), + // v3 is the default + ("1.53", None, 3), + ("1.53", Some(1), 1), + ("1.53", Some(2), 2), + ("1.53", Some(3), 3), + ("1.53", Some(4), 4), + // v4 introduced + ("1.78", None, 3), + // last version of v3 as the default + ("1.82", None, 3), + // v4 is the default + ("1.83", None, 4), + ("1.83", Some(1), 1), + ("1.83", Some(2), 2), + ("1.83", Some(3), 3), + ("1.83", Some(4), 4), + ]; + + for (msrv, existing_lockfile, expected_version) in cases { + // Clean previous lockfile. + _ = std::fs::remove_file(p.root().join("Cargo.lock")); + + p.change_file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + rust-version = "{msrv}" + + [dependencies] + bar = "0.1.0" + "#, + ), + ); + + if let Some(existing_lockfile) = existing_lockfile { + let existing_lockfile = match existing_lockfile { + 1 => v1_lockfile.as_str().into(), + 2 => v2_lockfile.as_str().into(), + 3 => v3_lockfile.as_str().into(), + v => std::borrow::Cow::from(format!("version = {v}")), + }; + p.change_file("Cargo.lock", &existing_lockfile); + } + + p.cargo("fetch").run(); + + let lock = p.read_lockfile(); + let toml = lock.parse::().unwrap(); + // get `version = ` from Cargo.lock + let version_field = toml.get("version").and_then(|v| v.as_integer()); + + let actual_version = if let Some(ver) = version_field { + ver + } else if lock.find("\nchecksum = ").is_some() { + 2 + } else { + 1 + }; + + assert_eq!( + expected_version, actual_version, + "msrv: {msrv}, existing lockfile: {existing_lockfile:?}" + ); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_path.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_path.rs new file mode 100644 index 000000000..b382064bf --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lockfile_path.rs @@ -0,0 +1,556 @@ +//! Tests for `lockfile-path` flag + +use std::fs; + +use snapbox::str; + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::install::assert_has_installed_exe; +use cargo_test_support::registry::{Package, RegistryBuilder}; +use cargo_test_support::{ + basic_bin_manifest, cargo_process, cargo_test, paths, project, symlink_supported, + ProjectBuilder, +}; +/////////////////////////////// +//// Unstable feature tests start +/////////////////////////////// + +#[cargo_test] +fn must_have_unstable_options() { + let lockfile_path = "mylockfile/is/burried/Cargo.lock"; + let p = make_project().build(); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("--lockfile-path") + .arg(lockfile_path) + .with_stderr_data(str![[ + r#"[ERROR] the `--lockfile-path` flag is unstable, pass `-Z unstable-options` to enable it +See https://github.com/rust-lang/cargo/issues/14421 for more information about the `--lockfile-path` flag. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn must_be_nightly() { + let lockfile_path = "mylockfile/is/burried/Cargo.lock"; + let p = make_project().build(); + + p.cargo("generate-lockfile") + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .with_stderr_data(str![[ + r#"[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels. + +"#]]) + .with_status(101) + .run(); +} + +/////////////////////////////// +//// Unstable feature tests end +/////////////////////////////// + +#[cargo_test] +fn basic_lockfile_created() { + let lockfile_path = "mylockfile/is/burried/Cargo.lock"; + let p = make_project().build(); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .run(); + assert!(!p.root().join("Cargo.lock").exists()); + assert!(p.root().join(lockfile_path).is_file()); +} + +#[cargo_test] +fn basic_lockfile_read() { + let lockfile_path = "mylockfile/Cargo.lock"; + let p = make_project().file(lockfile_path, VALID_LOCKFILE).build(); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .run(); + + assert!(!p.root().join("Cargo.lock").exists()); + assert!(p.root().join(lockfile_path).is_file()); +} + +#[cargo_test] +fn basic_lockfile_override() { + let lockfile_path = "mylockfile/Cargo.lock"; + let p = make_project() + .file("Cargo.lock", "This is an invalid lock file!") + .build(); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .run(); + + assert!(p.root().join(lockfile_path).is_file()); +} + +////////////////////// +///// Symlink tests +////////////////////// + +#[cargo_test] +fn symlink_in_path() { + if !symlink_supported() { + return; + } + + let dst = "dst"; + let src = "somedir/link"; + let lockfile_path = format!("{src}/Cargo.lock"); + + let p = make_project().symlink_dir(dst, src).build(); + + fs::create_dir(p.root().join("dst")).unwrap(); + assert!(p.root().join(src).is_dir()); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path.as_str()) + .run(); + + assert!(p.root().join(lockfile_path).is_file()); + assert!(p.root().join(dst).join("Cargo.lock").is_file()); +} + +#[cargo_test] +fn symlink_lockfile() { + if !symlink_supported() { + return; + } + + let lockfile_path = "dst/Cargo.lock"; + let src = "somedir/link"; + let lock_body = VALID_LOCKFILE; + + let p = make_project() + .file(lockfile_path, lock_body) + .symlink(lockfile_path, src) + .build(); + + assert!(p.root().join(src).is_file()); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .run(); + + assert!(!p.root().join("Cargo.lock").exists()); +} + +#[cargo_test] +fn broken_symlink() { + if !symlink_supported() { + return; + } + + let invalid_dst = "invalid_path"; + let src = "somedir/link"; + let lockfile_path = format!("{src}/Cargo.lock"); + + let p = make_project().symlink_dir(invalid_dst, src).build(); + assert!(!p.root().join(src).is_dir()); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .with_status(101) + .with_stderr_data(str![[ + r#"[ERROR] failed to create directory `[ROOT]/foo/somedir/link` + +... + +"# + ]]) + .run(); +} + +#[cargo_test] +fn loop_symlink() { + if !symlink_supported() { + return; + } + + let loop_link = "loop"; + let src = "somedir/link"; + let lockfile_path = format!("{src}/Cargo.lock"); + + let p = make_project() + .symlink_dir(loop_link, src) + .symlink_dir(src, loop_link) + .build(); + assert!(!p.root().join(src).is_dir()); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .with_status(101) + .with_stderr_data(str![[ + r#"[ERROR] failed to create directory `[ROOT]/foo/somedir/link` + +... + +"# + ]]) + .run(); +} + +///////////////////////// +//// Commands tests +///////////////////////// + +#[cargo_test] +fn add_lockfile_override() { + let lockfile_path = "mylockfile/Cargo.lock"; + project() + .at("bar") + .file("Cargo.toml", LIB_TOML) + .file("src/main.rs", "fn main() {}") + .build(); + let p = make_project() + .file("Cargo.lock", "This is an invalid lock file!") + .build(); + p.cargo("add") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .arg("--path") + .arg("../bar") + .run(); + + assert!(p.root().join(lockfile_path).is_file()); +} + +#[cargo_test] +fn clean_lockfile_override() { + let lockfile_path = "mylockfile/Cargo.lock"; + let p = make_project() + .file("Cargo.lock", "This is an invalid lock file!") + .build(); + p.cargo("clean") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .arg("--package") + .arg("test_foo") + .run(); + + assert!(p.root().join(lockfile_path).is_file()); +} + +#[cargo_test] +fn fix_lockfile_override() { + let lockfile_path = "mylockfile/Cargo.lock"; + let p = make_project() + .file("Cargo.lock", "This is an invalid lock file!") + .build(); + p.cargo("fix") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .arg("--package") + .arg("test_foo") + .arg("--allow-no-vcs") + .run(); + + assert!(p.root().join(lockfile_path).is_file()); +} + +#[cargo_test] +fn publish_lockfile_read() { + let lockfile_path = "mylockfile/Cargo.lock"; + let p = make_project().file(lockfile_path, VALID_LOCKFILE).build(); + let registry = RegistryBuilder::new().http_api().http_index().build(); + + p.cargo("publish") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .replace_crates_io(registry.index_url()) + .run(); + + assert!(!p.root().join("Cargo.lock").exists()); + assert!(p.root().join(lockfile_path).is_file()); +} + +#[cargo_test] +fn remove_lockfile_override() { + let lockfile_path = "mylockfile/Cargo.lock"; + let manifest = r#" + [package] + + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + edition = "2015" + + [[bin]] + + name = "foo" + + [dependencies] + test_bar = { version = "0.1.0", path = "../bar" } + "#; + + project() + .at("bar") + .file("Cargo.toml", LIB_TOML) + .file("src/main.rs", "fn main() {}") + .build(); + + let p = project() + .file("Cargo.toml", &manifest) + .file("src/main.rs", "fn main() {}") + .file("Cargo.lock", "This is an invalid lock file!") + .build(); + p.cargo("remove") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .arg("test_bar") + .run(); + + assert!(p.root().join(lockfile_path).is_file()); +} + +#[cargo_test] +fn assert_respect_pinned_version_from_lockfile_path() { + let lockfile_path = "mylockfile/Cargo.lock"; + let p = project() + .file( + "Cargo.toml", + r#"# +[package] + +name = "test_foo" +version = "0.5.0" +authors = ["wycats@example.com"] +edition = "2015" + +[[bin]] + +name = "test_foo" + +[dependencies] +bar = "0.1.0" +"#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.1.0").publish(); + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .run(); + + assert!(!p.root().join("Cargo.lock").exists()); + assert!(p.root().join(lockfile_path).is_file()); + + let lockfile_original = fs::read_to_string(p.root().join(lockfile_path)).unwrap(); + + Package::new("bar", "0.1.1").publish(); + p.cargo("package") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("--lockfile-path") + .arg(lockfile_path) + .run(); + + assert!(p + .root() + .join("target/package/test_foo-0.5.0/Cargo.lock") + .is_file()); + + let path = p.root().join("target/package/test_foo-0.5.0/Cargo.lock"); + let contents = fs::read_to_string(path).unwrap(); + + assert_e2e().eq(contents, lockfile_original); +} + +#[cargo_test] +fn install_respects_lock_file_path() { + // `cargo install` will imply --locked when lockfile path is provided + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.1") + .file("src/lib.rs", "not rust") + .publish(); + // Publish with lockfile containing bad version of `bar` (0.1.1) + Package::new("foo", "0.1.0") + .dep("bar", "0.1") + .file("src/lib.rs", "") + .file( + "src/main.rs", + "extern crate foo; extern crate bar; fn main() {}", + ) + .file( + "Cargo.lock", + r#" +[[package]] +name = "bar" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "bar 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] +"#, + ) + .publish(); + + cargo_process("install foo --locked") + .with_stderr_data(str![[r#" +... +[..]not rust[..] +... +"#]]) + .with_status(101) + .run(); + + // Create lockfile with the good `bar` version (0.1.0) and use it for install + project() + .file( + "Cargo.lock", + r#" +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] +"#, + ) + .build(); + cargo_process("install foo -Zunstable-options --lockfile-path foo/Cargo.lock") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .run(); + + assert!(paths::root().join("foo/Cargo.lock").is_file()); + assert_has_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn install_lock_file_path_must_present() { + // `cargo install` will imply --locked when lockfile path is provided + Package::new("bar", "0.1.0").publish(); + Package::new("foo", "0.1.0") + .dep("bar", "0.1") + .file("src/lib.rs", "") + .file( + "src/main.rs", + "extern crate foo; extern crate bar; fn main() {}", + ) + .publish(); + + cargo_process("install foo -Zunstable-options --lockfile-path lockfile_dir/Cargo.lock") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .with_stderr_data(str![[r#" +... +[ERROR] no Cargo.lock file found in the requested path [ROOT]/lockfile_dir/Cargo.lock +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn run_embed() { + let lockfile_path = "mylockfile/Cargo.lock"; + let invalid_lockfile = "Cargo.lock"; + let p = project() + .file("src/main.rs", "fn main() {}") + .file("Cargo.lock", "This is an invalid lock file!") + .build(); + + p.cargo("run") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("-Zscript") + .arg("--lockfile-path") + .arg(lockfile_path) + .arg("--manifest-path") + .arg("src/main.rs") + .run(); + + assert!(p.root().join(lockfile_path).is_file()); + + p.cargo("run") + .masquerade_as_nightly_cargo(&["lockfile-path"]) + .arg("-Zunstable-options") + .arg("-Zscript") + .arg("--lockfile-path") + .arg(invalid_lockfile) + .arg("--manifest-path") + .arg("src/main.rs") + .with_status(101) + .with_stderr_data(str![[ + r#"[WARNING] `package.edition` is unspecified, defaulting to `2024` +[ERROR] failed to parse lock file at: [ROOT]/foo/Cargo.lock + +... +"# + ]]) + .run(); +} + +const VALID_LOCKFILE: &str = r#"# Test lockfile +version = 4 + +[[package]] +name = "test_foo" +version = "0.5.0" +"#; + +const LIB_TOML: &str = r#" + [package] + name = "test_bar" + version = "0.1.0" + edition = "2021" + "#; + +fn make_project() -> ProjectBuilder { + project() + .file("Cargo.toml", &basic_bin_manifest("test_foo")) + .file("src/main.rs", "fn main() {}") +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/login.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/login.rs new file mode 100644 index 000000000..cac0e718a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/login.rs @@ -0,0 +1,388 @@ +//! Tests for the `cargo login` command. + +use std::fs; +use std::path::PathBuf; + +use cargo_test_support::cargo_process; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, RegistryBuilder}; +use cargo_test_support::str; +use cargo_test_support::t; + +const TOKEN: &str = "test-token"; +const TOKEN2: &str = "test-token2"; +const ORIGINAL_TOKEN: &str = "api-token"; + +fn credentials_toml() -> PathBuf { + paths::home().join(".cargo/credentials.toml") +} + +fn setup_new_credentials() { + setup_new_credentials_at(credentials_toml()); +} + +fn setup_new_credentials_at(config: PathBuf) { + t!(fs::create_dir_all(config.parent().unwrap())); + t!(fs::write( + &config, + format!(r#"token = "{token}""#, token = ORIGINAL_TOKEN) + )); +} + +/// Asserts whether or not the token is set to the given value for the given registry. +pub fn check_token(expected_token: Option<&str>, registry: Option<&str>) { + let credentials = credentials_toml(); + assert!(credentials.is_file()); + + let contents = fs::read_to_string(&credentials).unwrap(); + let toml: toml::Table = contents.parse().unwrap(); + + let actual_token = match registry { + // A registry has been provided, so check that the token exists in a + // table for the registry. + Some(registry) => toml + .get("registries") + .and_then(|registries_table| registries_table.get(registry)) + .and_then(|registry_table| match registry_table.get("token") { + Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()), + _ => None, + }), + // There is no registry provided, so check the global token instead. + None => toml + .get("registry") + .and_then(|registry_table| registry_table.get("token")) + .and_then(|v| match v { + toml::Value::String(ref token) => Some(token.as_str().to_string()), + _ => None, + }), + }; + + match (actual_token, expected_token) { + (None, None) => {} + (Some(actual), Some(expected)) => assert_eq!(actual, expected), + (None, Some(expected)) => { + panic!("expected `{registry:?}` to be `{expected}`, but was not set") + } + (Some(actual), None) => { + panic!("expected `{registry:?}` to be unset, but was set to `{actual}`") + } + } +} + +#[cargo_test] +fn registry_credentials() { + let _alternative = RegistryBuilder::new().alternative().build(); + let _alternative2 = RegistryBuilder::new() + .alternative_named("alternative2") + .build(); + + setup_new_credentials(); + + let reg = "alternative"; + + cargo_process("login --registry") + .arg(reg) + .with_stdin(TOKEN) + .run(); + + // Ensure that we have not updated the default token + check_token(Some(ORIGINAL_TOKEN), None); + + // Also ensure that we get the new token for the registry + check_token(Some(TOKEN), Some(reg)); + + let reg2 = "alternative2"; + cargo_process("login --registry") + .arg(reg2) + .with_stdin(TOKEN2) + .run(); + + // Ensure not overwriting 1st alternate registry token with + // 2nd alternate registry token (see rust-lang/cargo#7701). + check_token(Some(ORIGINAL_TOKEN), None); + check_token(Some(TOKEN), Some(reg)); + check_token(Some(TOKEN2), Some(reg2)); +} + +#[cargo_test] +fn empty_login_token() { + let registry = RegistryBuilder::new() + .no_configure_registry() + .no_configure_token() + .build(); + setup_new_credentials(); + + cargo_process("login") + .replace_crates_io(registry.index_url()) + .with_stdin("\t\n") + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +please paste the token found on [ROOTURL]/api/me below +[ERROR] credential provider `cargo:token` failed action `login` + +Caused by: + please provide a non-empty token + +"#]]) + .with_status(101) + .run(); + + cargo_process("login") + .replace_crates_io(registry.index_url()) + .with_stdin("") + .with_stderr_data(str![[r#" +please paste the token found on [ROOTURL]/api/me below +[ERROR] credential provider `cargo:token` failed action `login` + +Caused by: + please provide a non-empty token + +"#]]) + .with_status(101) + .run(); + + cargo_process("login") + .replace_crates_io(registry.index_url()) + .arg("") + .with_stdin("") + .with_stderr_data(str![[r#" +[WARNING] `cargo login ` is deprecated in favor of reading `` from stdin +[ERROR] credential provider `cargo:token` failed action `login` + +Caused by: + please provide a non-empty token + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn invalid_login_token() { + let registry = RegistryBuilder::new() + .no_configure_registry() + .no_configure_token() + .build(); + setup_new_credentials(); + + let check = |stdin: &str, stderr: &str, status: i32| { + cargo_process("login") + .replace_crates_io(registry.index_url()) + .with_stdin(stdin) + .with_stderr_data(stderr) + .with_status(status) + .run(); + }; + + let invalid = |stdin: &str| { + check( + stdin, + "[ERROR] credential provider `cargo:token` failed action `login` + +Caused by: + token contains invalid characters. + Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header. +", + 101, + ) + }; + let valid = |stdin: &str| { + check( + stdin, + "\ +[LOGIN] token for `crates-io` saved +", + 0, + ) + }; + + // Update config.json so that the rest of the tests don't need to care + // whether or not `Updating` is printed. + check( + "test", + "\ +[UPDATING] crates.io index +[LOGIN] token for `crates-io` saved +", + 0, + ); + + invalid("😄"); + invalid("\u{0016}"); + invalid("\u{0000}"); + invalid("你好"); + valid("foo\tbar"); + valid("foo bar"); + valid( + r##"!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"##, + ); +} + +#[cargo_test] +fn bad_asymmetric_token_args() { + let registry = RegistryBuilder::new() + .credential_provider(&["cargo:paseto"]) + .no_configure_token() + .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 -Zasymmetric-token -- --key-subject") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] credential provider `cargo:paseto --key-subject` failed action `login` + +Caused by: + [ERROR] a value is required for '--key-subject ' but none was supplied + + For more information, try '--help'. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn login_with_no_cargo_dir() { + // Create a config in the root directory because `login` requires the + // index to be updated, and we don't want to hit crates.io. + let registry = registry::init(); + fs::rename(paths::home().join(".cargo"), paths::root().join(".cargo")).unwrap(); + paths::home().rm_rf(); + cargo_process("login foo -v") + .replace_crates_io(registry.index_url()) + .run(); + let credentials = fs::read_to_string(credentials_toml()).unwrap(); + assert_eq!(credentials, "[registry]\ntoken = \"foo\"\n"); +} + +#[cargo_test] +fn login_with_asymmetric_token_and_subject_on_stdin() { + let registry = RegistryBuilder::new() + .credential_provider(&["cargo:paseto"]) + .no_configure_token() + .build(); + let credentials = credentials_toml(); + cargo_process("login -v -Z asymmetric-token -- --key-subject=foo") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[CREDENTIAL] cargo:paseto --key-subject=foo login crates-io +k3.public.AmDwjlyf8jAV3gm5Z7Kz9xAOcsKslt_Vwp5v-emjFzBHLCtcANzTaVEghTNEMj9PkQ + +"#]]) + .with_stdin("k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36") + .run(); + let credentials = fs::read_to_string(&credentials).unwrap(); + assert!(credentials.starts_with("[registry]\n")); + assert!(credentials.contains("secret-key-subject = \"foo\"\n")); + assert!(credentials.contains("secret-key = \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n")); +} + +#[cargo_test] +fn login_with_differently_sized_token() { + // Verify that the configuration file gets properly truncated. + let registry = registry::init(); + let credentials = credentials_toml(); + fs::remove_file(&credentials).unwrap(); + cargo_process("login lmaolmaolmao -v") + .replace_crates_io(registry.index_url()) + .run(); + cargo_process("login lmao -v") + .replace_crates_io(registry.index_url()) + .run(); + cargo_process("login lmaolmaolmao -v") + .replace_crates_io(registry.index_url()) + .run(); + let credentials = fs::read_to_string(&credentials).unwrap(); + assert_eq!(credentials, "[registry]\ntoken = \"lmaolmaolmao\"\n"); +} + +#[cargo_test] +fn login_with_token_on_stdin() { + let registry = registry::init(); + let credentials = credentials_toml(); + fs::remove_file(&credentials).unwrap(); + cargo_process("login lmao -v") + .replace_crates_io(registry.index_url()) + .run(); + cargo_process("login") + .replace_crates_io(registry.index_url()) + .with_stdin("some token") + .run(); + let credentials = fs::read_to_string(&credentials).unwrap(); + assert_eq!(credentials, "[registry]\ntoken = \"some token\"\n"); +} + +#[cargo_test] +fn login_with_asymmetric_token_on_stdin() { + let _registry = RegistryBuilder::new() + .credential_provider(&["cargo:paseto"]) + .alternative() + .no_configure_token() + .build(); + let credentials = credentials_toml(); + cargo_process("login -v -Z asymmetric-token --registry alternative") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[CREDENTIAL] cargo:paseto login alternative +k3.public.AmDwjlyf8jAV3gm5Z7Kz9xAOcsKslt_Vwp5v-emjFzBHLCtcANzTaVEghTNEMj9PkQ + +"#]]) + .with_stdin("k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36") + .run(); + let credentials = fs::read_to_string(&credentials).unwrap(); + assert_eq!(credentials, "[registries.alternative]\nsecret-key = \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n"); +} + +#[cargo_test] +fn login_with_generate_asymmetric_token() { + let _registry = RegistryBuilder::new() + .credential_provider(&["cargo:paseto"]) + .alternative() + .no_configure_token() + .build(); + let credentials = credentials_toml(); + cargo_process("login -Z asymmetric-token --registry alternative") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +k3.public.[..] + +"#]]) + .run(); + let credentials = fs::read_to_string(&credentials).unwrap(); + assert!(credentials.contains("secret-key = \"k3.secret.")); +} + +#[cargo_test] +fn default_registry_configured() { + // When registry.default is set, login should use that one when + // --registry is not used. + let _alternative = RegistryBuilder::new().alternative().build(); + let cargo_home = paths::home().join(".cargo"); + cargo_util::paths::append( + &cargo_home.join("config.toml"), + br#" + [registry] + default = "alternative" + "#, + ) + .unwrap(); + + cargo_process("login") + .with_stdin("a-new-token") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOGIN] token for `alternative` saved + +"#]]) + .run(); + + check_token(None, None); + check_token(Some("a-new-token"), Some("alternative")); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/logout.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/logout.rs new file mode 100644 index 000000000..aa2ac38fc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/logout.rs @@ -0,0 +1,129 @@ +//! Tests for the `cargo logout` command. + +use super::login::check_token; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::TestRegistry; +use cargo_test_support::{cargo_process, registry, str}; + +fn simple_logout_test(registry: &TestRegistry, reg: Option<&str>, flag: &str, note: &str) { + let msg = reg.unwrap_or("crates-io"); + check_token(Some(registry.token()), reg); + let mut cargo = cargo_process(&format!("logout {}", flag)); + if reg.is_none() { + cargo.replace_crates_io(registry.index_url()); + } + cargo + .with_stderr_data(&format!( + "\ +[LOGOUT] token for `{msg}` has been removed from local storage +[NOTE] This does not revoke the token on the registry server. + If you need to revoke the token, visit {note} and follow the instructions there. +" + )) + .run(); + check_token(None, reg); + + let mut cargo = cargo_process(&format!("logout {}", flag)); + if reg.is_none() { + cargo.replace_crates_io(registry.index_url()); + } + cargo + .with_stderr_data(&format!( + "\ +[LOGOUT] not currently logged in to `{msg}` +" + )) + .run(); + check_token(None, reg); +} + +#[cargo_test] +fn default_registry_unconfigured() { + let registry = registry::init(); + simple_logout_test(®istry, None, "", ""); +} + +#[cargo_test] +fn other_registry() { + let registry = registry::alt_init(); + simple_logout_test( + ®istry, + Some("alternative"), + "--registry alternative", + "the `alternative` website", + ); + // It should not touch crates.io. + check_token(Some("sekrit"), None); +} + +#[cargo_test] +fn default_registry_configured() { + // When registry.default is set, logout should use that one when + // --registry is not used. + let cargo_home = paths::home().join(".cargo"); + cargo_home.mkdir_p(); + cargo_util::paths::write( + &cargo_home.join("config.toml"), + r#" + [registry] + default = "dummy-registry" + + [registries.dummy-registry] + index = "https://127.0.0.1/index" + "#, + ) + .unwrap(); + cargo_util::paths::write( + &cargo_home.join("credentials.toml"), + r#" + [registry] + token = "crates-io-token" + + [registries.dummy-registry] + token = "dummy-token" + "#, + ) + .unwrap(); + check_token(Some("dummy-token"), Some("dummy-registry")); + check_token(Some("crates-io-token"), None); + + cargo_process("logout").with_stderr_data(str![[r#" +[LOGOUT] token for `dummy-registry` has been removed from local storage +[NOTE] This does not revoke the token on the registry server. + If you need to revoke the token, visit the `dummy-registry` website and follow the instructions there. + +"#]]).run(); + check_token(None, Some("dummy-registry")); + check_token(Some("crates-io-token"), None); + + cargo_process("logout") + .with_stderr_data(str![[r#" +[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_data(str![[r#" +[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_data(str![[r#" +[LOGOUT] not currently logged in to `crates-io` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lto.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lto.rs new file mode 100644 index 000000000..21b96f956 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/lto.rs @@ -0,0 +1,945 @@ +use cargo::core::compiler::Lto; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::RawOutput; +use cargo_test_support::{basic_manifest, project, str, Project}; + +#[cargo_test] +fn with_deps() { + Package::new("bar", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + + [dependencies] + bar = "*" + + [profile.release] + lto = true + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() {}") + .build(); + p.cargo("build -v --release") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto [..]` +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test [..]-C lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn shared_deps() { + Package::new("bar", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + + [dependencies] + bar = "*" + + [build-dependencies] + bar = "*" + + [profile.release] + lto = true + "#, + ) + .file("build.rs", "extern crate bar; fn main() {}") + .file("src/main.rs", "extern crate bar; fn main() {}") + .build(); + p.cargo("build -v --release") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto [..]` +[RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no [..]` +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/release/build/test-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name test [..]-C lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn build_dep_not_ltod() { + Package::new("bar", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + + [build-dependencies] + bar = "*" + + [profile.release] + lto = true + "#, + ) + .file("build.rs", "extern crate bar; fn main() {}") + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("build -v --release") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no [..]` +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/release/build/test-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name test [..]-C lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn complicated() { + Package::new("dep-shared", "0.0.1") + .file("src/lib.rs", "pub fn foo() {}") + .publish(); + Package::new("dep-normal2", "0.0.1") + .file("src/lib.rs", "pub fn foo() {}") + .publish(); + Package::new("dep-normal", "0.0.1") + .dep("dep-shared", "*") + .dep("dep-normal2", "*") + .file( + "src/lib.rs", + " + pub fn foo() { + dep_shared::foo(); + dep_normal2::foo(); + } + ", + ) + .publish(); + Package::new("dep-build2", "0.0.1") + .file("src/lib.rs", "pub fn foo() {}") + .publish(); + Package::new("dep-build", "0.0.1") + .dep("dep-shared", "*") + .dep("dep-build2", "*") + .file( + "src/lib.rs", + " + pub fn foo() { + dep_shared::foo(); + dep_build2::foo(); + } + ", + ) + .publish(); + Package::new("dep-proc-macro2", "0.0.1") + .file("src/lib.rs", "pub fn foo() {}") + .publish(); + Package::new("dep-proc-macro", "0.0.1") + .proc_macro(true) + .dep("dep-shared", "*") + .dep("dep-proc-macro2", "*") + .file( + "src/lib.rs", + " + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_attribute] + pub fn foo(_: TokenStream, a: TokenStream) -> TokenStream { + dep_shared::foo(); + dep_proc_macro2::foo(); + a + } + ", + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + + [lib] + crate-type = ['cdylib', 'staticlib'] + + [dependencies] + dep-normal = "*" + dep-proc-macro = "*" + + [build-dependencies] + dep-build = "*" + + [profile.release] + lto = true + + # force build deps to share an opt-level with the rest of the + # graph so they only get built once. + [profile.release.build-override] + opt-level = 3 + "#, + ) + .file("build.rs", "fn main() { dep_build::foo() }") + .file( + "src/bin/foo-bin.rs", + "#[dep_proc_macro::foo] fn main() { dep_normal::foo() }", + ) + .file( + "src/lib.rs", + "#[dep_proc_macro::foo] pub fn foo() { dep_normal::foo() }", + ) + .build(); + p.cargo("build -v --release") + // normal deps and their transitive dependencies do not need object + // code, so they should have linker-plugin-lto specified + .with_stderr_contains( + "[..]`rustc[..]--crate-name dep_normal2 [..]-C linker-plugin-lto[..]`", + ) + .with_stderr_contains("[..]`rustc[..]--crate-name dep_normal [..]-C linker-plugin-lto[..]`") + // build dependencies and their transitive deps don't need any bitcode, + // so embedding should be turned off + .with_stderr_contains("[..]`rustc[..]--crate-name dep_build2 [..]-C embed-bitcode=no[..]`") + .with_stderr_contains("[..]`rustc[..]--crate-name dep_build [..]-C embed-bitcode=no[..]`") + .with_stderr_contains( + "[..]`rustc[..]--crate-name build_script_build [..]-C embed-bitcode=no[..]`", + ) + // proc macro deps are the same as build deps here + .with_stderr_contains( + "[..]`rustc[..]--crate-name dep_proc_macro2 [..]-C embed-bitcode=no[..]`", + ) + .with_stderr_contains( + "[..]`rustc[..]--crate-name dep_proc_macro [..]-C embed-bitcode=no[..]`", + ) + .with_stderr_contains( + "[..]`rustc[..]--crate-name foo_bin [..]--crate-type bin[..]-C lto[..]`", + ) + .with_stderr_contains( + "[..]`rustc[..]--crate-name test [..]--crate-type cdylib[..]-C lto[..]`", + ) + .with_stderr_contains("[..]`rustc[..]--crate-name dep_shared [..]`") + .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C lto[..]") + .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C linker-plugin-lto[..]") + .with_stderr_does_not_contain("[..]--crate-name dep_shared[..]-C embed-bitcode[..]") + .run(); +} + +#[cargo_test] +fn off_in_manifest_works() { + Package::new("bar", "0.0.1") + .file("src/lib.rs", "pub fn foo() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + + [dependencies] + bar = "*" + + [profile.release] + lto = "off" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + "fn main() { + test::foo(); + bar::foo(); + }", + ) + .build(); + p.cargo("build -v --release") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C lto=off [..]-C embed-bitcode=no [..]` +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test [..]--crate-type lib [..]-C lto=off [..]-C embed-bitcode=no [..]` +[RUNNING] `rustc --crate-name test --edition=2015 src/main.rs [..]--crate-type bin [..]-C lto=off [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn between_builds() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + + [profile.release] + lto = true + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file("src/main.rs", "fn main() { test::foo() }") + .build(); + p.cargo("build -v --release --lib") + .with_stderr_data(str![[r#" +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]--crate-type lib [..]-C linker-plugin-lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build -v --release") + .with_stderr_data(str![[r#" +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]--crate-type bin [..]-C lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn test_all() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [profile.release] + lto = true + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("tests/a.rs", "") + .file("tests/b.rs", "") + .build(); + p.cargo("test --release -v") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name a [..]-C lto [..]` +[RUNNING] `rustc --crate-name b [..]-C lto [..]` +[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]` +[RUNNING] `rustc --crate-name foo [..]--crate-type bin [..]-C lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_all_and_bench() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [profile.release] + lto = true + [profile.bench] + lto = true + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("tests/a.rs", "") + .file("tests/b.rs", "") + .build(); + p.cargo("test --release -v") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name a [..]-C lto [..]` +[RUNNING] `rustc --crate-name b [..]-C lto [..]` +[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]` +[RUNNING] `rustc --crate-name foo [..]--crate-type bin [..]-C lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); +} + +/// Basic setup: +/// +/// foo v0.0.0 +/// ├── bar v0.0.0 +/// │ ├── registry v0.0.1 +/// │ └── registry-shared v0.0.1 +/// └── registry-shared v0.0.1 +/// +/// Where `bar` will have the given crate types. +fn project_with_dep(crate_types: &str) -> Project { + Package::new("registry", "0.0.1") + .file("src/lib.rs", r#"pub fn foo() { println!("registry"); }"#) + .publish(); + Package::new("registry-shared", "0.0.1") + .file("src/lib.rs", r#"pub fn foo() { println!("shared"); }"#) + .publish(); + + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [workspace] + + [dependencies] + bar = { path = 'bar' } + registry-shared = "*" + + [profile.release] + lto = true + "#, + ) + .file( + "src/main.rs", + " + fn main() { + bar::foo(); + registry_shared::foo(); + } + ", + ) + .file( + "bar/Cargo.toml", + &format!( + r#" + [package] + name = "bar" + version = "0.0.0" + edition = "2015" + + [dependencies] + registry = "*" + registry-shared = "*" + + [lib] + crate-type = [{}] + "#, + crate_types + ), + ) + .file( + "bar/src/lib.rs", + r#" + pub fn foo() { + println!("bar"); + registry::foo(); + registry_shared::foo(); + } + "#, + ) + .file("tests/a.rs", "") + .file("bar/tests/b.rs", "") + .build() +} + +/// Helper for checking which LTO behavior is used for a specific crate. +/// +/// `krate_info` is extra compiler flags used to distinguish this if the same +/// crate name is being built multiple times. +fn verify_lto(output: &RawOutput, krate: &str, krate_info: &str, expected_lto: Lto) { + let stderr = std::str::from_utf8(&output.stderr).unwrap(); + let mut matches = stderr.lines().filter(|line| { + line.contains("Running") + && line.contains(&format!("--crate-name {} ", krate)) + && line.contains(krate_info) + }); + let line = matches.next().unwrap_or_else(|| { + panic!( + "expected to find crate `{}` info: `{}`, not found in output:\n{}", + krate, krate_info, stderr + ); + }); + if let Some(line2) = matches.next() { + panic!( + "found multiple lines matching crate `{}` info: `{}`:\nline1:{}\nline2:{}\noutput:\n{}", + krate, krate_info, line, line2, stderr + ); + } + 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 { + Lto::Run(Some(mode.into())) + } + } else if line.contains("-C lto") { + Lto::Run(None) + } else if line.contains("-C linker-plugin-lto") { + Lto::OnlyBitcode + } else if line.contains("-C embed-bitcode=no") { + Lto::OnlyObject + } else { + Lto::ObjectAndBitcode + }; + assert_eq!( + actual_lto, expected_lto, + "did not find expected LTO in line: {}", + line + ); +} + +#[cargo_test] +fn cdylib_and_rlib() { + let p = project_with_dep("'cdylib', 'rlib'"); + let output = p.cargo("build --release -v").run(); + // `registry` is ObjectAndBitcode because it needs Object for the + // rlib, and Bitcode for the cdylib (which doesn't support LTO). + verify_lto( + &output, + "registry", + "--crate-type lib", + Lto::ObjectAndBitcode, + ); + // Same as `registry` + verify_lto( + &output, + "registry_shared", + "--crate-type lib", + Lto::ObjectAndBitcode, + ); + // Same as `registry` + verify_lto( + &output, + "bar", + "--crate-type cdylib --crate-type rlib", + Lto::ObjectAndBitcode, + ); + verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None)); + p.cargo("test --release -v") + .with_stderr_data( + str![[r#" +[FRESH] registry v0.0.1 +[FRESH] registry-shared v0.0.1 +[FRESH] bar v0.0.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]` +[RUNNING] `rustc --crate-name a [..]-C lto [..]--test [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); + p.cargo("build --release -v --manifest-path bar/Cargo.toml") + .with_stderr_data( + str![[r#" +[FRESH] registry-shared v0.0.1 +[FRESH] registry v0.0.1 +[FRESH] bar v0.0.0 ([ROOT]/foo/bar) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + p.cargo("test --release -v --manifest-path bar/Cargo.toml") + .with_stderr_data(str![[r#" +[FRESH] registry-shared v0.0.1 +[FRESH] registry v0.0.1 +[COMPILING] bar v0.0.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..]-C lto [..]--test [..]` +[RUNNING] `rustc --crate-name b [..]-C lto [..]--test [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/bar-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]` +[DOCTEST] bar +[RUNNING] `rustdoc --edition=2015 --crate-type cdylib --crate-type rlib --color auto --crate-name bar --test [..]-C lto [..] + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn dylib() { + let p = project_with_dep("'dylib'"); + let output = p.cargo("build --release -v").run(); + // `registry` is OnlyObject because rustc doesn't support LTO with dylibs. + verify_lto(&output, "registry", "--crate-type lib", Lto::OnlyObject); + // `registry_shared` is both because it is needed by both bar (Object) and + // foo (Bitcode for LTO). + verify_lto( + &output, + "registry_shared", + "--crate-type lib", + Lto::ObjectAndBitcode, + ); + // `bar` is OnlyObject because rustc doesn't support LTO with dylibs. + verify_lto(&output, "bar", "--crate-type dylib", Lto::OnlyObject); + // `foo` is LTO because it is a binary, and the profile specifies `lto=true`. + verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None)); + // `cargo test` should not rebuild dependencies. It builds the test + // executables with `lto=true` because the tests are built with the + // `--release` flag. + p.cargo("test --release -v") + .with_stderr_data( + str![[r#" +[FRESH] registry v0.0.1 +[FRESH] registry-shared v0.0.1 +[FRESH] bar v0.0.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]-C lto [..]--test [..]` +[RUNNING] `rustc --crate-name a [..]-C lto [..]--test [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); + // Building just `bar` causes `registry-shared` to get rebuilt because it + // switches to OnlyObject because it is now only being used with a dylib + // which does not support LTO. + // + // `bar` gets rebuilt because `registry_shared` got rebuilt. + p.cargo("build --release -v --manifest-path bar/Cargo.toml") + .with_stderr_data( + str![[r#" +[COMPILING] registry-shared v0.0.1 +[FRESH] registry v0.0.1 +[RUNNING] `rustc --crate-name registry_shared [..]-C embed-bitcode=no [..]` +[DIRTY] bar v0.0.0 ([..]): dependency info changed +[COMPILING] bar v0.0.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + // Testing just `bar` causes `registry` to get rebuilt because it switches + // to needing both Object (for the `bar` dylib) and Bitcode (for the test + // built with LTO). + // + // `bar` the dylib gets rebuilt because `registry` got rebuilt. + p.cargo("test --release -v --manifest-path bar/Cargo.toml") + .with_stderr_data( + str![[r#" +[FRESH] registry-shared v0.0.1 +[COMPILING] registry v0.0.1 +[RUNNING] `rustc --crate-name registry [..]` +[DIRTY] bar v0.0.0 ([..]): dependency info changed +[COMPILING] bar v0.0.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..]--crate-type dylib [..]-C embed-bitcode=no [..]` +[RUNNING] `rustc --crate-name bar [..]-C lto [..]--test [..]` +[RUNNING] `rustc --crate-name b [..]-C lto [..]--test [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/bar-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/b-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +// This is currently broken on windows-gnu, see https://github.com/rust-lang/rust/issues/109797 +#[cfg_attr( + all(target_os = "windows", target_env = "gnu"), + ignore = "windows-gnu not working" +)] +fn test_profile() { + Package::new("bar", "0.0.1") + .file("src/lib.rs", "pub fn foo() -> i32 { 123 } ") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [profile.test] + lto = 'thin' + + [dependencies] + bar = "*" + "#, + ) + .file( + "src/lib.rs", + r#" + #[test] + fn t1() { + assert_eq!(123, bar::foo()); + } + "#, + ) + .build(); + + p.cargo("test -v") + // unordered because the two `foo` builds start in parallel + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]` +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]--crate-type lib --emit=dep-info,metadata,link -C linker-plugin-lto [..]` +[RUNNING] `rustc --crate-name foo [..]--emit=dep-info,link -C lto=thin [..]--test [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc [..] + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn doctest() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [profile.release] + lto = true + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + r#" + /// Foo! + /// + /// ``` + /// foo::foo(); + /// ``` + pub fn foo() { bar::bar(); } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file( + "bar/src/lib.rs", + r#" + pub fn bar() { println!("hi!"); } + "#, + ) + .build(); + + p.cargo("test --doc --release -v") + // embed-bitcode should be harmless here + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..]-C linker-plugin-lto [..]` +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]--crate-type lib [..]-C linker-plugin-lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[DOCTEST] foo +[RUNNING] `rustdoc [..]` + +"#]]) + .run(); + + // Try with bench profile. + p.cargo("test --doc --release -v") + .env("CARGO_PROFILE_BENCH_LTO", "true") + .with_stderr_data( + str![[r#" +[DOCTEST] foo +[RUNNING] `rustdoc [..]-C lto [..]` +[FRESH] bar v0.1.0 ([ROOT]/foo/bar) +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn dylib_rlib_bin() { + // dylib+rlib linked with a binary + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [lib] + crate-type = ["dylib", "rlib"] + + [profile.release] + lto = true + "#, + ) + .file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }") + .file("src/bin/ferret.rs", "fn main() { foo::foo(); }") + .build(); + + let output = p.cargo("build --release -v").run(); + verify_lto( + &output, + "foo", + "--crate-type dylib --crate-type rlib", + Lto::ObjectAndBitcode, + ); + verify_lto(&output, "ferret", "--crate-type bin", Lto::Run(None)); +} + +#[cargo_test] +fn fresh_swapping_commands() { + // In some rare cases, different commands end up building dependencies + // with different LTO settings. This checks that it doesn't cause the + // cache to thrash in that scenario. + Package::new("bar", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + + [profile.release] + lto = true + "#, + ) + .file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }") + .build(); + + p.cargo("build --release -v") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[COMPILING] bar v1.0.0 +[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto [..]` +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]-C linker-plugin-lto [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("test --release -v") + .with_stderr_data( + str![[r#" +[FRESH] bar v1.0.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]-C lto [..]--test [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc [..]-C lto [..]` + +"#]] + .unordered(), + ) + .run(); + + p.cargo("build --release -v") + .with_stderr_data(str![[r#" +[FRESH] bar v1.0.0 +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("test --release -v --no-run -v") + .with_stderr_data(str![[r#" +[FRESH] bar v1.0.0 +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/main.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/main.rs new file mode 100644 index 000000000..385b3690b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/main.rs @@ -0,0 +1,198 @@ +#![allow(clippy::disallowed_methods)] +#![allow(clippy::print_stderr)] +#![allow(clippy::print_stdout)] + +mod advanced_env; +mod alt_registry; +mod artifact_dep; +mod artifact_dir; +mod bad_config; +mod bad_manifest_path; +mod bench; +mod binary_name; +mod build; +mod build_plan; +mod build_script; +mod build_script_env; +mod build_script_extra_link_arg; +mod cache_lock; +mod cache_messages; +mod cargo; +mod cargo_add; +mod cargo_alias_config; +mod cargo_bench; +mod cargo_build; +mod cargo_check; +mod cargo_clean; +mod cargo_command; +mod cargo_config; +mod cargo_doc; +mod cargo_env_config; +mod cargo_features; +mod cargo_fetch; +mod cargo_fix; +mod cargo_generate_lockfile; +mod cargo_git_checkout; +mod cargo_help; +mod cargo_info; +mod cargo_init; +mod cargo_install; +mod cargo_locate_project; +mod cargo_login; +mod cargo_logout; +mod cargo_metadata; +mod cargo_new; +mod cargo_owner; +mod cargo_package; +mod cargo_pkgid; +mod cargo_publish; +mod cargo_read_manifest; +mod cargo_remove; +mod cargo_report; +mod cargo_run; +mod cargo_rustc; +mod cargo_rustdoc; +mod cargo_search; +mod cargo_targets; +mod cargo_test; +mod cargo_tree; +mod cargo_uninstall; +mod cargo_update; +mod cargo_vendor; +mod cargo_verify_project; +mod cargo_version; +mod cargo_yank; +mod cfg; +mod check; +mod check_cfg; +mod clean; +mod collisions; +mod concurrent; +mod config; +mod config_cli; +mod config_include; +mod corrupt_git; +mod credential_process; +mod cross_compile; +mod cross_publish; +mod custom_target; +mod death; +mod dep_info; +mod diagnostics; +mod direct_minimal_versions; +mod directory; +mod doc; +mod docscrape; +mod edition; +mod error; +mod feature_unification; +mod features; +mod features2; +mod features_namespaced; +mod fetch; +mod fix; +mod fix_n_times; +mod freshness; +mod freshness_checksum; +mod future_incompat_report; +mod generate_lockfile; +mod git; +mod git_auth; +mod git_gc; +mod git_shallow; +mod glob_targets; +mod global_cache_tracker; +mod help; +mod https; +mod inheritable_workspace_fields; +mod install; +mod install_upgrade; +mod jobserver; +mod lints; +mod lints_table; +mod list_availables; +mod local_registry; +mod locate_project; +mod lockfile_compat; +mod lockfile_path; +mod login; +mod logout; +mod lto; +mod member_discovery; +mod member_errors; +mod message_format; +mod messages; +mod metabuild; +mod metadata; +mod minimal_versions; +mod multitarget; +mod net_config; +mod new; +mod offline; +mod old_cargos; +mod open_namespaces; +mod owner; +mod package; +mod package_features; +mod patch; +mod path; +mod paths; +mod pgo; +mod pkgid; +mod precise_pre_release; +mod proc_macro; +mod profile_config; +mod profile_custom; +mod profile_overrides; +mod profile_targets; +mod profile_trim_paths; +mod profiles; +mod progress; +mod pub_priv; +mod publish; +mod publish_lockfile; +mod read_manifest; +mod registry; +mod registry_auth; +mod registry_overlay; +mod rename_deps; +mod replace; +mod required_features; +mod run; +mod rust_version; +mod rustc; +mod rustc_info_cache; +mod rustdoc; +mod rustdoc_extern_html; +mod rustdocflags; +mod rustflags; +mod rustup; +mod script; +mod search; +mod shell_quoting; +mod source_replacement; +mod ssh; +mod standard_lib; +mod test; +mod timings; +mod tool_paths; +mod tree; +mod tree_graph_features; +mod unit_graph; +mod update; +mod vendor; +mod verify_project; +mod version; +mod warn_on_failure; +mod warning_override; +mod weak_dep_features; +mod workspaces; +mod yank; + +use cargo_test_support::prelude::*; + +#[cargo_test] +fn aaa_trigger_cross_compile_disabled_check() { + // This triggers the cross compile disabled check to run ASAP, see #5141 + cargo_test_support::cross_compile::disabled(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_discovery.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_discovery.rs new file mode 100644 index 000000000..c04e79427 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_discovery.rs @@ -0,0 +1,44 @@ +//! Tests for workspace member discovery. + +use cargo::core::{Shell, Workspace}; +use cargo::util::context::GlobalContext; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry; + +/// Tests exclusion of non-directory files from workspace member discovery using glob `*`. +#[cargo_test] +fn bad_file_member_exclusion() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [ "crates/*" ] + "#, + ) + .file("crates/.DS_Store", "PLACEHOLDER") + .file( + "crates/bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + "#, + ) + .file("crates/bar/src/main.rs", "fn main() {}") + .build(); + + // Prevent this test from accessing the network by setting up .cargo/config. + registry::init(); + let gctx = GlobalContext::new( + Shell::from_write(Box::new(Vec::new())), + paths::cargo_home(), + paths::cargo_home(), + ); + let ws = Workspace::new(&p.root().join("Cargo.toml"), &gctx).unwrap(); + assert_eq!(ws.members().count(), 1); + assert_eq!(ws.members().next().unwrap().name(), "bar"); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_errors.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_errors.rs new file mode 100644 index 000000000..1e99e9cba --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/member_errors.rs @@ -0,0 +1,168 @@ +//! Tests for workspace member errors. + +use cargo::core::resolver::ResolveError; +use cargo::core::{compiler::CompileMode, Shell, Workspace}; +use cargo::ops::{self, CompileOptions}; +use cargo::util::{context::GlobalContext, errors::ManifestError}; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry; +use cargo_test_support::str; + +/// Tests inclusion of a `ManifestError` pointing to a member manifest +/// when that manifest fails to deserialize. +#[cargo_test] +fn toml_deserialize_manifest_error() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + foobar == "0.55" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid string +expected `"`, `'` + --> bar/Cargo.toml:8:25 + | +8 | foobar == "0.55" + | ^ + | +[ERROR] failed to load manifest for dependency `bar` + +"#]]) + .run(); +} + +/// Tests inclusion of a `ManifestError` pointing to a member manifest +/// when that manifest has an invalid dependency path. +#[cargo_test] +fn member_manifest_path_io_error() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + foobar = { path = "nosuch" } + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + let root_manifest_path = p.root().join("Cargo.toml"); + let member_manifest_path = p.root().join("bar").join("Cargo.toml"); + let missing_manifest_path = p.root().join("bar").join("nosuch").join("Cargo.toml"); + + let error = + Workspace::new(&root_manifest_path, &GlobalContext::default().unwrap()).unwrap_err(); + eprintln!("{:?}", error); + + let manifest_err: &ManifestError = error.downcast_ref().expect("Not a ManifestError"); + assert_eq!(manifest_err.manifest_path(), &root_manifest_path); + + let causes: Vec<_> = manifest_err.manifest_causes().collect(); + assert_eq!(causes.len(), 2, "{:?}", causes); + assert_eq!(causes[0].manifest_path(), &member_manifest_path); + assert_eq!(causes[1].manifest_path(), &missing_manifest_path); +} + +/// Tests dependency version errors provide which package failed via a `ResolveError`. +#[cargo_test] +fn member_manifest_version_error() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + i-dont-exist = "0.55" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + // Prevent this test from accessing the network by setting up .cargo/config. + registry::init(); + let gctx = GlobalContext::new( + Shell::from_write(Box::new(Vec::new())), + paths::cargo_home(), + paths::cargo_home(), + ); + let ws = Workspace::new(&p.root().join("Cargo.toml"), &gctx).unwrap(); + let compile_options = CompileOptions::new(&gctx, CompileMode::Build).unwrap(); + let member_bar = ws.members().find(|m| &*m.name() == "bar").unwrap(); + + let error = ops::compile(&ws, &compile_options).map(|_| ()).unwrap_err(); + eprintln!("{:?}", error); + + let resolve_err: &ResolveError = error.downcast_ref().expect("Not a ResolveError"); + let package_path = resolve_err.package_path(); + assert_eq!(package_path.len(), 1, "package_path: {:?}", package_path); + assert_eq!(package_path[0], member_bar.package_id()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/message_format.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/message_format.rs new file mode 100644 index 000000000..16947c394 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/message_format.rs @@ -0,0 +1,164 @@ +//! Tests for --message-format flag. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_lib_manifest, basic_manifest, project, str}; + +#[cargo_test] +fn cannot_specify_two() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + let formats = ["human", "json", "short"]; + + for a in formats.iter() { + for b in formats.iter() { + p.cargo(&format!("build --message-format {},{}", a, b)) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify two kinds of `message-format` arguments + +"#]]) + .run(); + } + } +} + +#[cargo_test] +fn double_json_works() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check --message-format json,json-render-diagnostics") + .run(); + p.cargo("check --message-format json,json-diagnostic-short") + .run(); + p.cargo("check --message-format json,json-diagnostic-rendered-ansi") + .run(); + p.cargo("check --message-format json --message-format json-diagnostic-rendered-ansi") + .run(); + p.cargo("check --message-format json-diagnostic-rendered-ansi") + .run(); + p.cargo("check --message-format json-diagnostic-short,json-diagnostic-rendered-ansi") + .run(); +} + +#[cargo_test] +fn cargo_renders() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + + [dependencies] + bar = { path = 'bar' } + "#, + ) + .file("src/main.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check --message-format json-render-diagnostics") + .with_status(101) + .with_stdout_data( + str![[r#" +[ + { + "reason": "compiler-artifact", + "...": "{...}" + }, + { + "reason": "build-finished", + "success": false + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .with_stderr_contains( + "\ +[CHECKING] bar [..] +[CHECKING] foo [..] +error[..]`main`[..] +", + ) + .run(); +} + +#[cargo_test] +fn cargo_renders_short() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "") + .build(); + + p.cargo("check --message-format json-render-diagnostics,json-diagnostic-short") + .with_status(101) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +error[E0601]: `main` function not found in crate `foo` +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_renders_ansi() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/main.rs", "") + .build(); + + p.cargo("check --message-format json-diagnostic-rendered-ansi") + .with_status(101) + .with_stdout_contains("[..]\\u001b[38;5;9merror[..]") + .run(); +} + +#[cargo_test] +fn cargo_renders_doctests() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/lib.rs", + "\ + /// ```rust + /// bar() + /// ``` + pub fn bar() {} + ", + ) + .build(); + + p.cargo("test --doc --message-format short") + .with_status(101) + .with_stdout_data(str![[r#" + +running 1 test +test src/lib.rs - bar (line 1) ... FAILED + +failures: + +---- src/lib.rs - bar (line 1) stdout ---- +src/lib.rs:2:1: error[E0425]: cannot find function `bar`[..] +[ERROR] aborting due to 1 previous error +Couldn't compile the test. + +failures: + src/lib.rs - bar (line 1) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/messages.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/messages.rs new file mode 100644 index 000000000..c00f88be0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/messages.rs @@ -0,0 +1,164 @@ +//! General tests specifically about diagnostics and other messages. +//! +//! Tests for message caching can be found in `cache_messages`. + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::prelude::*; +use cargo_test_support::{process, project, Project}; +use cargo_util::ProcessError; + +/// Captures the actual diagnostics displayed by rustc. This is done to avoid +/// relying on the exact message formatting in rustc. +pub fn raw_rustc_output(project: &Project, path: &str, extra: &[&str]) -> String { + let mut proc = process("rustc"); + if cfg!(windows) { + // Sanitize in case the caller wants to do direct string comparison with Cargo's output. + proc.arg(path.replace('/', "\\")); + } else { + proc.arg(path); + } + let rustc_output = match proc + .arg("--crate-type=lib") + .args(extra) + .cwd(project.root()) + .exec_with_output() + { + Ok(output) => output.stderr, + Err(e) => e.downcast::().unwrap().stderr.unwrap(), + }; + // Do a little dance to remove rustc's "warnings emitted" message and the subsequent newline. + let stderr = std::str::from_utf8(&rustc_output).expect("utf8"); + let mut lines = stderr.lines(); + let mut result = String::new(); + while let Some(line) = lines.next() { + if line.contains("warning emitted") + || line.contains("warnings emitted") + || line.contains("aborting due to") + { + // Eat blank line. + match lines.next() { + None | Some("") => continue, + Some(s) => panic!("unexpected str {}", s), + } + } + result.push_str(line); + result.push('\n'); + } + result +} + +fn redact_rustc_message(msg: &str) -> impl IntoData { + use snapbox::filter::{Filter, FilterPaths}; + let assert = assert_e2e(); + let redactions = assert.redactions(); + let msg = redactions.redact(msg); + FilterPaths.filter(msg.into()) +} + +#[cargo_test] +fn deduplicate_messages_basic() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() { + let x = 1; + } + "#, + ) + .build(); + let rustc_message = raw_rustc_output(&p, "src/lib.rs", &[]); + let expected_output = format!( + "{}\ +[WARNING] `foo` (lib) generated 1 warning[..] +[WARNING] `foo` (lib test) generated 1 warning (1 duplicate) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +", + rustc_message + ); + p.cargo("test --no-run -j1") + .with_stderr_data(redact_rustc_message(&format!( + "\ +[COMPILING] foo v0.0.1 ([ROOT]/foo) +{}", + expected_output + ))) + .run(); + // Run again, to check for caching behavior. + p.cargo("test --no-run -j1") + .with_stderr_data(redact_rustc_message(&expected_output)) + .run(); +} + +#[cargo_test] +fn deduplicate_messages_mismatched_warnings() { + // One execution prints 1 warning, the other prints 2 where there is an overlap. + let p = project() + .file( + "src/lib.rs", + r#" + pub fn foo() { + let x = 1; + } + + #[test] + fn t1() { + let MY_VALUE = 1; + assert_eq!(MY_VALUE, 1); + } + "#, + ) + .build(); + let lib_output = raw_rustc_output(&p, "src/lib.rs", &[]); + let mut lib_test_output = raw_rustc_output(&p, "src/lib.rs", &["--test"]); + // Remove the duplicate warning. + let start = lib_test_output.find(&lib_output).expect("same warning"); + lib_test_output.replace_range(start..start + lib_output.len(), ""); + let expected_output = format!( + "\ +{}\ +[WARNING] `foo` (lib) generated 1 warning[..] +{}\ +[WARNING] `foo` (lib test) generated 2 warnings (1 duplicate) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +", + lib_output, lib_test_output + ); + p.cargo("test --no-run -j1") + .with_stderr_data(redact_rustc_message(&format!( + "\ +[COMPILING] foo v0.0.1 ([ROOT]/foo) +{}", + expected_output + ))) + .run(); + // Run again, to check for caching behavior. + p.cargo("test --no-run -j1") + .with_stderr_data(redact_rustc_message(&expected_output)) + .run(); +} + +#[cargo_test] +fn deduplicate_errors() { + let p = project() + .file( + "src/lib.rs", + r#" + this should not compile + "#, + ) + .build(); + let rustc_message = raw_rustc_output(&p, "src/lib.rs", &[]); + p.cargo("test -j1") + .with_status(101) + .with_stderr_data(redact_rustc_message(&format!( + "\ +[COMPILING] foo v0.0.1 ([ROOT]/foo) +{}[ERROR] could not compile `foo` (lib) due to 1 previous error +", + rustc_message + ))) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metabuild.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metabuild.rs new file mode 100644 index 000000000..51f0fa959 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metabuild.rs @@ -0,0 +1,829 @@ +//! Tests for the metabuild feature (declarative build scripts). + +use std::str; + +use cargo_test_support::prelude::*; +use cargo_test_support::{ + basic_lib_manifest, basic_manifest, is_coarse_mtime, project, registry::Package, rustc_host, + str, Project, +}; + +#[cargo_test] +fn metabuild_gated() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + metabuild = ["mb"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `metabuild` is required + + The package requires the Cargo feature called `metabuild`, but that feature is not stabilized in this version of Cargo ([..]). + Consider adding `cargo-features = ["metabuild"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#metabuild for more information about the status of this feature. + +"#]]) + .run(); +} + +fn basic_project() -> Project { + project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + metabuild = ["mb", "mb-other"] + + [build-dependencies] + mb = {path="mb"} + mb-other = {path="mb-other"} + "#, + ) + .file("src/lib.rs", "") + .file("mb/Cargo.toml", &basic_lib_manifest("mb")) + .file( + "mb/src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb"); }"#, + ) + .file( + "mb-other/Cargo.toml", + r#" + [package] + name = "mb-other" + version = "0.0.1" + edition = "2015" + "#, + ) + .file( + "mb-other/src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb-other"); }"#, + ) + .build() +} + +#[cargo_test] +fn metabuild_basic() { + let p = basic_project(); + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_data(str![[r#" +[foo 0.0.1] Hello mb +[foo 0.0.1] Hello mb-other + +"#]]) + .run(); +} + +#[cargo_test] +fn metabuild_error_both() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + metabuild = "mb" + + [build-dependencies] + mb = {path="mb"} + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", r#"fn main() {}"#) + .file("mb/Cargo.toml", &basic_lib_manifest("mb")) + .file( + "mb/src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb"); }"#, + ) + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + cannot specify both `metabuild` and `build` + +"#]]) + .run(); +} + +#[cargo_test] +fn metabuild_missing_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + metabuild = "mb" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + metabuild package `mb` must be specified in `build-dependencies` + +"#]]) + .run(); +} + +#[cargo_test] +fn metabuild_optional_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + metabuild = "mb" + + [build-dependencies] + mb = {path="mb", optional=true} + "#, + ) + .file("src/lib.rs", "") + .file("mb/Cargo.toml", &basic_lib_manifest("mb")) + .file( + "mb/src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb"); }"#, + ) + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_does_not_contain("[foo 0.0.1] Hello mb") + .run(); + + p.cargo("check -vv --features mb") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_contains("[foo 0.0.1] Hello mb") + .run(); +} + +#[cargo_test] +fn metabuild_lib_name() { + // Test when setting `name` on [lib]. + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + metabuild = "mb" + + [build-dependencies] + mb = {path="mb"} + "#, + ) + .file("src/lib.rs", "") + .file( + "mb/Cargo.toml", + r#" + [package] + name = "mb" + version = "0.0.1" + edition = "2015" + [lib] + name = "other" + "#, + ) + .file( + "mb/src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb"); }"#, + ) + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_data(str![[r#" +[foo 0.0.1] Hello mb + +"#]]) + .run(); +} + +#[cargo_test] +fn metabuild_fresh() { + if is_coarse_mtime() { + // This test doesn't work on coarse mtimes very well. Because the + // metabuild script is created at build time, its mtime is almost + // always equal to the mtime of the output. The second call to `build` + // will then think it needs to be rebuilt when it should be fresh. + return; + } + + // Check that rebuild is fresh. + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + metabuild = "mb" + + [build-dependencies] + mb = {path="mb"} + "#, + ) + .file("src/lib.rs", "") + .file("mb/Cargo.toml", &basic_lib_manifest("mb")) + .file( + "mb/src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb"); }"#, + ) + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_contains("[foo 0.0.1] Hello mb") + .run(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_does_not_contain("[foo 0.0.1] Hello mb") + .with_stderr_data(str![[r#" +[FRESH] mb v0.5.0 ([ROOT]/foo/mb) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn metabuild_links() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + links = "cat" + metabuild = "mb" + + [build-dependencies] + mb = {path="mb"} + "#, + ) + .file("src/lib.rs", "") + .file("mb/Cargo.toml", &basic_lib_manifest("mb")) + .file( + "mb/src/lib.rs", + r#" + pub fn metabuild() { + assert_eq!(std::env::var("CARGO_MANIFEST_LINKS"), + Ok("cat".to_string())); + println!("Hello mb"); + } + "#, + ) + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_data(str![[r#" +[foo 0.0.1] Hello mb + +"#]]) + .run(); +} + +#[cargo_test] +fn metabuild_override() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + links = "cat" + metabuild = "mb" + + [build-dependencies] + mb = {path="mb"} + "#, + ) + .file("src/lib.rs", "") + .file("mb/Cargo.toml", &basic_lib_manifest("mb")) + .file( + "mb/src/lib.rs", + r#"pub fn metabuild() { panic!("should not run"); }"#, + ) + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}.cat] + rustc-link-lib = ["a"] + "#, + rustc_host() + ), + ) + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .run(); +} + +#[cargo_test] +fn metabuild_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["member1", "member2"] + "#, + ) + .file( + "member1/Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "member1" + version = "0.0.1" + edition = "2015" + metabuild = ["mb1", "mb2"] + + [build-dependencies] + mb1 = {path="../../mb1"} + mb2 = {path="../../mb2"} + "#, + ) + .file("member1/src/lib.rs", "") + .file( + "member2/Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "member2" + version = "0.0.1" + edition = "2015" + metabuild = ["mb1"] + + [build-dependencies] + mb1 = {path="../../mb1"} + "#, + ) + .file("member2/src/lib.rs", "") + .build(); + + project() + .at("mb1") + .file("Cargo.toml", &basic_lib_manifest("mb1")) + .file( + "src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb1 {}", std::env::var("CARGO_MANIFEST_DIR").unwrap()); }"#, + ) + .build(); + + project() + .at("mb2") + .file("Cargo.toml", &basic_lib_manifest("mb2")) + .file( + "src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb2 {}", std::env::var("CARGO_MANIFEST_DIR").unwrap()); }"#, + ) + .build(); + + p.cargo("check -vv --workspace") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_contains("[member1 0.0.1] Hello mb1 [..]member1") + .with_stdout_contains("[member1 0.0.1] Hello mb2 [..]member1") + .with_stdout_contains("[member2 0.0.1] Hello mb1 [..]member2") + .with_stdout_does_not_contain("[member2 0.0.1] Hello mb2 [..]member2") + .run(); +} + +#[cargo_test] +fn metabuild_metadata() { + // The metabuild Target is filtered out of the `metadata` results. + let p = basic_project(); + + let meta = p + .cargo("metadata --format-version=1") + .masquerade_as_nightly_cargo(&["metabuild"]) + .run_json(); + let mb_info: Vec<&str> = meta["packages"] + .as_array() + .unwrap() + .iter() + .find(|p| p["name"].as_str().unwrap() == "foo") + .unwrap()["metabuild"] + .as_array() + .unwrap() + .iter() + .map(|s| s.as_str().unwrap()) + .collect(); + assert_eq!(mb_info, ["mb", "mb-other"]); +} + +#[cargo_test] +fn metabuild_build_plan() { + let p = basic_project(); + + p.cargo("build --build-plan -Zunstable-options") + .masquerade_as_nightly_cargo(&["metabuild", "build-plan"]) + .with_stdout_data( + str![[r#" +{ + "inputs": [ + "[ROOT]/foo/Cargo.toml", + "[ROOT]/foo/mb/Cargo.toml", + "[ROOT]/foo/mb-other/Cargo.toml" + ], + "invocations": [ + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [], + "env": "{...}", + "kind": null, + "links": {}, + "outputs": [ + "[ROOT]/foo/target/debug/deps/libmb-[HASH].rlib", + "[ROOT]/foo/target/debug/deps/libmb-[HASH].rmeta" + ], + "package_name": "mb", + "package_version": "0.5.0", + "program": "rustc", + "target_kind": [ + "lib" + ] + }, + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [], + "env": "{...}", + "kind": null, + "links": {}, + "outputs": [ + "[ROOT]/foo/target/debug/deps/libmb_other-[HASH].rlib", + "[ROOT]/foo/target/debug/deps/libmb_other-[HASH].rmeta" + ], + "package_name": "mb-other", + "package_version": "0.0.1", + "program": "rustc", + "target_kind": [ + "lib" + ] + }, + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [ + 0, + 1 + ], + "env": "{...}", + "kind": null, + "links": "{...}", + "outputs": "{...}", + "package_name": "foo", + "package_version": "0.0.1", + "program": "rustc", + "target_kind": [ + "custom-build" + ] + }, + { + "args": "{...}", + "compile_mode": "run-custom-build", + "cwd": "[ROOT]/foo", + "deps": [ + 2 + ], + "env": "{...}", + "kind": null, + "links": {}, + "outputs": [], + "package_name": "foo", + "package_version": "0.0.1", + "program": "[ROOT]/foo/target/debug/build/foo-[HASH]/metabuild-foo", + "target_kind": [ + "custom-build" + ] + }, + { + "args": "{...}", + "compile_mode": "build", + "cwd": "[ROOT]/foo", + "deps": [ + 3 + ], + "env": "{...}", + "kind": null, + "links": "{...}", + "outputs": [ + "[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib", + "[ROOT]/foo/target/debug/deps/libfoo-[HASH].rmeta" + ], + "package_name": "foo", + "package_version": "0.0.1", + "program": "rustc", + "target_kind": [ + "lib" + ] + } + ] +} +"#]] + .is_json(), + ) + .run(); + + assert_eq!(p.glob("target/.metabuild/metabuild-foo-*.rs").count(), 1); +} + +#[cargo_test] +fn metabuild_two_versions() { + // Two versions of a metabuild dep with the same name. + let p = project() + .at("ws") + .file( + "Cargo.toml", + r#" + [workspace] + members = ["member1", "member2"] + "#, + ) + .file( + "member1/Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "member1" + version = "0.0.1" + edition = "2015" + metabuild = ["mb"] + + [build-dependencies] + mb = {path="../../mb1"} + "#, + ) + .file("member1/src/lib.rs", "") + .file( + "member2/Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "member2" + version = "0.0.1" + edition = "2015" + metabuild = ["mb"] + + [build-dependencies] + mb = {path="../../mb2"} + "#, + ) + .file("member2/src/lib.rs", "") + .build(); + + project().at("mb1") + .file("Cargo.toml", r#" + [package] + name = "mb" + version = "0.0.1" + edition = "2015" + "#) + .file( + "src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb1 {}", std::env::var("CARGO_MANIFEST_DIR").unwrap()); }"#, + ) + .build(); + + project().at("mb2") + .file("Cargo.toml", r#" + [package] + name = "mb" + version = "0.0.2" + edition = "2015" + "#) + .file( + "src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb2 {}", std::env::var("CARGO_MANIFEST_DIR").unwrap()); }"#, + ) + .build(); + + p.cargo("check -vv --workspace") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_data( + str![[r#" +[member2 0.0.1] Hello mb2 [ROOT]/ws/member2 +[member1 0.0.1] Hello mb1 [ROOT]/ws/member1 + +"#]] + .unordered(), + ) + .run(); + + assert_eq!( + p.glob("target/.metabuild/metabuild-member?-*.rs").count(), + 2 + ); +} + +#[cargo_test] +fn metabuild_external_dependency() { + Package::new("mb", "1.0.0") + .file("Cargo.toml", &basic_manifest("mb", "1.0.0")) + .file( + "src/lib.rs", + r#"pub fn metabuild() { println!("Hello mb"); }"#, + ) + .publish(); + Package::new("dep", "1.0.0") + .file( + "Cargo.toml", + r#" + cargo-features = ["metabuild"] + [package] + name = "dep" + version = "1.0.0" + edition = "2015" + metabuild = ["mb"] + + [build-dependencies] + mb = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build_dep("mb", "1.0.0") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + [dependencies] + dep = "1.0" + "#, + ) + .file("src/lib.rs", "extern crate dep;") + .build(); + + p.cargo("check -vv") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_data(str![[r#" +[dep 1.0.0] Hello mb + +"#]]) + .run(); + + assert_eq!(p.glob("target/.metabuild/metabuild-dep-*.rs").count(), 1); +} + +#[cargo_test] +fn metabuild_json_artifact() { + let p = basic_project(); + p.cargo("check --message-format=json") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_stdout_data( + str![[r#" +[ + "{...}", + { + "executable": null, + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "bin" + ], + "doc": false, + "doctest": false, + "edition": "2018", + "kind": [ + "custom-build" + ], + "name": "metabuild-foo", + "src_path": "[ROOT]/foo/target/.metabuild/metabuild-foo-[HASH].rs", + "test": false + } + }, + { + "cfgs": [], + "env": [], + "linked_libs": [], + "linked_paths": [], + "out_dir": "[ROOT]/foo/target/debug/build/foo-[HASH]/out", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "reason": "build-script-executed" + }, + "{...}" +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn metabuild_failed_build_json() { + let p = basic_project(); + // Modify the metabuild dep so that it fails to compile. + p.change_file("mb/src/lib.rs", ""); + p.cargo("check --message-format=json") + .masquerade_as_nightly_cargo(&["metabuild"]) + .with_status(101) + .with_stdout_data( + str![[r#" +[ + "{...}", + { + "manifest_path": "[ROOT]/foo/Cargo.toml", + "message": { + "level": "error", + "message": "cannot find function `metabuild` in crate `mb`", + "...": "{...}" + }, + "package_id": "path+[ROOTURL]/foo#0.0.1", + "reason": "compiler-message", + "target": { + "crate_types": [ + "bin" + ], + "doc": false, + "doctest": false, + "edition": "2018", + "kind": [ + "custom-build" + ], + "name": "metabuild-foo", + "src_path": null, + "test": false + } + }, + "{...}" +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metadata.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metadata.rs new file mode 100644 index 000000000..5c9015a87 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/metadata.rs @@ -0,0 +1,4956 @@ +//! Tests for the `cargo metadata` command. + +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{ + basic_bin_manifest, basic_lib_manifest, main_file, project, rustc_host, str, +}; +use serde_json::json; + +#[cargo_test] +fn cargo_metadata_simple() { + let p = project() + .file("src/foo.rs", "") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/foo.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.5.0" + } + ], + "root": "path+[ROOTURL]/foo#0.5.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_warns_on_implicit_version() { + let p = project() + .file("src/foo.rs", "") + .file("Cargo.toml", &basic_bin_manifest("foo")) + .build(); + + p.cargo("metadata") + .with_stderr_data(str![[r#" +[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems + +"#]]) + .run(); + + p.cargo("metadata --format-version 1") + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn library_with_several_crate_types() { + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.5.0" + +[lib] +crate-type = ["lib", "staticlib"] + "#, + ) + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib", + "staticlib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib", + "staticlib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.5.0" + } + ], + "root": "path+[ROOTURL]/foo#0.5.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn library_with_features() { + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.5.0" + +[features] +default = ["default_feat"] +default_feat = [] +optional_feat = [] + "#, + ) + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": { + "default": [ + "default_feat" + ], + "default_feat": [], + "optional_feat": [] + }, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [ + "default", + "default_feat" + ], + "id": "path+[ROOTURL]/foo#0.5.0" + } + ], + "root": "path+[ROOTURL]/foo#0.5.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_with_deps_and_version() { + let p = project() + .file("src/foo.rs", "") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + authors = [] + license = "MIT" + description = "foo" + + [[bin]] + name = "foo" + + [dependencies] + bar = "*" + [dev-dependencies] + foobar = "*" + "#, + ) + .build(); + Package::new("baz", "0.0.1").publish(); + Package::new("foobar", "0.0.1").publish(); + Package::new("bar", "0.0.1").dep("baz", "0.0.1").publish(); + + p.cargo("metadata -q --format-version 1") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "baz", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.0.1", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/Cargo.toml", + "metadata": null, + "name": "baz", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "baz", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/baz-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "bar", + "optional": false, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": "dev", + "name": "foobar", + "optional": false, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": "foo", + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/foo.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/Cargo.toml", + "metadata": null, + "name": "foobar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foobar", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "baz", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1" + } + ], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#baz@0.0.1" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "bar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": "dev", + "target": null + } + ], + "name": "foobar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.5.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.5.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +/// The `public` field should not show up in `cargo metadata` output if `-Zpublic-dependency` +/// is not enabled +#[cargo_test] +fn cargo_metadata_public_private_dependencies_disabled() { + let p = project() + .file("src/foo.rs", "") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + authors = [] + license = "MIT" + description = "foo" + + [[bin]] + name = "foo" + + [dependencies] + bar = { version = "*", public = false } + foobar = { version = "*", public = true } + baz = "*" + "#, + ) + .build(); + Package::new("bar", "0.0.1").publish(); + Package::new("foobar", "0.0.2").publish(); + Package::new("baz", "0.0.3").publish(); + + p.cargo("metadata -q --format-version 1") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "name": "bar", + "...": "{...}" + }, + { + "name": "baz", + "...": "{...}" + }, + { + "name": "foo", + "dependencies": [ + { + "features": [], + "kind": null, + "name": "bar", + "optional": false, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "baz", + "optional": false, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "foobar", + "optional": false, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "...": "{...}" + }, + { + "name": "foobar", + "...": "{...}" + } + ], + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_public_private_dependencies_enabled() { + let p = project() + .file("src/foo.rs", "") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + authors = [] + license = "MIT" + description = "foo" + + [[bin]] + name = "foo" + + [dependencies] + bar = { version = "*", public = false } + foobar = { version = "*", public = true } + baz = "*" + "#, + ) + .build(); + Package::new("bar", "0.0.1").publish(); + Package::new("foobar", "0.0.2").publish(); + Package::new("baz", "0.0.3").publish(); + + p.cargo("metadata -q --format-version 1 -Zpublic-dependency") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "name": "bar", + "...": "{...}" + }, + { + "name": "baz", + "...": "{...}" + }, + { + "name": "foo", + "dependencies": [ + { + "features": [], + "kind": null, + "name": "bar", + "optional": false, + "public": false, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "baz", + "optional": false, + "public": false, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "foobar", + "optional": false, + "public": true, + "registry": null, + "rename": null, + "req": "*", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "...": "{...}" + }, + { + "name": "foobar", + "...": "{...}" + } + ], + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn example() { + let p = project() + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.1.0" + +[[example]] +name = "ex" + "#, + ) + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": false, + "doctest": false, + "edition": "2015", + "kind": [ + "example" + ], + "name": "ex", + "src_path": "[ROOT]/foo/examples/ex.rs", + "test": false + } + ], + "version": "0.1.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn example_lib() { + let p = project() + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.1.0" + +[[example]] +name = "ex" +crate-type = ["rlib", "dylib"] + "#, + ) + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + }, + { + "crate_types": [ + "rlib", + "dylib" + ], + "doc": false, + "doctest": false, + "edition": "2015", + "kind": [ + "example" + ], + "name": "ex", + "src_path": "[ROOT]/foo/examples/ex.rs", + "test": false + } + ], + "version": "0.1.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn workspace_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + + [workspace.metadata] + tool1 = "hello" + tool2 = [1, 2, 3] + + [workspace.metadata.foo] + bar = 3 + + "#, + ) + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": { + "foo": { + "bar": 3 + }, + "tool1": "hello", + "tool2": [ + 1, + 2, + 3 + ] + }, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/bar#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/bar/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/foo/bar/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/baz#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/baz/Cargo.toml", + "metadata": null, + "name": "baz", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "baz", + "src_path": "[ROOT]/foo/baz/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/bar#0.5.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/baz#0.5.0" + } + ], + "root": null + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/baz#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/baz#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn workspace_metadata_with_dependencies_no_deps() { + let p = project() + // NOTE that 'artifact' isn't mentioned in the workspace here, yet it shows up as member. + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + baz = { path = "../baz/" } + artifact = { path = "../artifact/", artifact = "bin" } + "#, + ) + .file("bar/src/lib.rs", "") + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file("baz/src/lib.rs", "") + .file("artifact/Cargo.toml", &basic_bin_manifest("artifact")) + .file("artifact/src/main.rs", "fn main() {}") + .build(); + + p.cargo("metadata --no-deps -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [ + { + "artifact": { + "kinds": [ + "bin" + ], + "lib": false, + "target": null + }, + "features": [], + "kind": null, + "name": "artifact", + "optional": false, + "path": "[ROOT]/foo/artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "baz", + "optional": false, + "path": "[ROOT]/foo/baz", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/bar#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/bar/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/foo/bar/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/artifact#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/artifact/Cargo.toml", + "metadata": null, + "name": "artifact", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "artifact", + "src_path": "[ROOT]/foo/artifact/src/main.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/baz#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/baz/Cargo.toml", + "metadata": null, + "name": "baz", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "baz", + "src_path": "[ROOT]/foo/baz/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/artifact#0.5.0", + "path+[ROOTURL]/foo/baz#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/artifact#0.5.0", + "path+[ROOTURL]/foo/baz#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn workspace_metadata_with_dependencies_and_resolve() { + let alt_target = "wasm32-unknown-unknown"; + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "artifact", "non-artifact", "bin-only-artifact"] + "#, + ) + .file( + "bar/Cargo.toml", + &r#" + [package] + + name = "bar" + version = "0.5.0" + authors = [] + + [build-dependencies] + artifact = { path = "../artifact/", artifact = "bin", target = "target" } + bin-only-artifact = { path = "../bin-only-artifact/", artifact = "bin", target = "$ALT_TARGET" } + non-artifact = { path = "../non-artifact" } + + [dependencies] + artifact = { path = "../artifact/", artifact = ["cdylib", "staticlib", "bin:baz-name"], lib = true, target = "$ALT_TARGET" } + bin-only-artifact = { path = "../bin-only-artifact/", artifact = "bin:a-name" } + non-artifact = { path = "../non-artifact" } + + [dev-dependencies] + artifact = { path = "../artifact/" } + non-artifact = { path = "../non-artifact" } + bin-only-artifact = { path = "../bin-only-artifact/", artifact = "bin:b-name" } + "#.replace("$ALT_TARGET", alt_target), + ) + .file("bar/src/lib.rs", "") + .file("bar/build.rs", "fn main() {}") + .file( + "artifact/Cargo.toml", + r#" + [package] + name = "artifact" + version = "0.5.0" + authors = [] + + [lib] + crate-type = ["staticlib", "cdylib", "rlib"] + + [[bin]] + name = "bar-name" + + [[bin]] + name = "baz-name" + "#, + ) + .file("artifact/src/main.rs", "fn main() {}") + .file("artifact/src/lib.rs", "") + .file( + "bin-only-artifact/Cargo.toml", + r#" + [package] + name = "bin-only-artifact" + version = "0.5.0" + authors = [] + + [[bin]] + name = "a-name" + + [[bin]] + name = "b-name" + "#, + ) + .file("bin-only-artifact/src/main.rs", "fn main() {}") + .file("non-artifact/Cargo.toml", + r#" + [package] + + name = "non-artifact" + version = "0.5.0" + authors = [] + "#, + ) + .file("non-artifact/src/lib.rs", "") + .build(); + + p.cargo("metadata -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/artifact#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/artifact/Cargo.toml", + "metadata": null, + "name": "artifact", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "staticlib", + "cdylib", + "rlib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "staticlib", + "cdylib", + "rlib" + ], + "name": "artifact", + "src_path": "[ROOT]/foo/artifact/src/lib.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "bar-name", + "src_path": "[ROOT]/foo/artifact/src/main.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "baz-name", + "src_path": "[ROOT]/foo/artifact/src/main.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "artifact": { + "kinds": [ + "cdylib", + "staticlib", + "bin:baz-name" + ], + "lib": true, + "target": "wasm32-unknown-unknown" + }, + "features": [], + "kind": null, + "name": "artifact", + "optional": false, + "path": "[ROOT]/foo/artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "artifact": { + "kinds": [ + "bin:a-name" + ], + "lib": false, + "target": null + }, + "features": [], + "kind": null, + "name": "bin-only-artifact", + "optional": false, + "path": "[ROOT]/foo/bin-only-artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "non-artifact", + "optional": false, + "path": "[ROOT]/foo/non-artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": "dev", + "name": "artifact", + "optional": false, + "path": "[ROOT]/foo/artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "artifact": { + "kinds": [ + "bin:b-name" + ], + "lib": false, + "target": null + }, + "features": [], + "kind": "dev", + "name": "bin-only-artifact", + "optional": false, + "path": "[ROOT]/foo/bin-only-artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": "dev", + "name": "non-artifact", + "optional": false, + "path": "[ROOT]/foo/non-artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "artifact": { + "kinds": [ + "bin" + ], + "lib": false, + "target": "target" + }, + "features": [], + "kind": "build", + "name": "artifact", + "optional": false, + "path": "[ROOT]/foo/artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "artifact": { + "kinds": [ + "bin" + ], + "lib": false, + "target": "wasm32-unknown-unknown" + }, + "features": [], + "kind": "build", + "name": "bin-only-artifact", + "optional": false, + "path": "[ROOT]/foo/bin-only-artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": "build", + "name": "non-artifact", + "optional": false, + "path": "[ROOT]/foo/non-artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/bar#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/bar/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/foo/bar/src/lib.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": false, + "doctest": false, + "edition": "2015", + "kind": [ + "custom-build" + ], + "name": "build-script-build", + "src_path": "[ROOT]/foo/bar/build.rs", + "test": false + } + ], + "version": "0.5.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/bin-only-artifact#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/bin-only-artifact/Cargo.toml", + "metadata": null, + "name": "bin-only-artifact", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "a-name", + "src_path": "[ROOT]/foo/bin-only-artifact/src/main.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "b-name", + "src_path": "[ROOT]/foo/bin-only-artifact/src/main.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/non-artifact#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/non-artifact/Cargo.toml", + "metadata": null, + "name": "non-artifact", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "non_artifact", + "src_path": "[ROOT]/foo/non-artifact/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/artifact#0.5.0" + }, + { + "dependencies": [ + "path+[ROOTURL]/foo/artifact#0.5.0", + "path+[ROOTURL]/foo/bin-only-artifact#0.5.0", + "path+[ROOTURL]/foo/non-artifact#0.5.0" + ], + "deps": [ + { + "dep_kinds": [ + { + "extern_name": "artifact", + "kind": null, + "target": null + }, + { + "artifact": "cdylib", + "compile_target": "wasm32-unknown-unknown", + "extern_name": "artifact", + "kind": null, + "target": null + }, + { + "artifact": "staticlib", + "compile_target": "wasm32-unknown-unknown", + "extern_name": "artifact", + "kind": null, + "target": null + }, + { + "artifact": "bin", + "bin_name": "baz-name", + "compile_target": "wasm32-unknown-unknown", + "extern_name": "baz_name", + "kind": null, + "target": null + }, + { + "kind": "dev", + "target": null + }, + { + "artifact": "bin", + "bin_name": "bar-name", + "compile_target": "", + "extern_name": "bar_name", + "kind": "build", + "target": null + }, + { + "artifact": "bin", + "bin_name": "baz-name", + "compile_target": "", + "extern_name": "baz_name", + "kind": "build", + "target": null + } + ], + "name": "artifact", + "pkg": "path+[ROOTURL]/foo/artifact#0.5.0" + }, + { + "dep_kinds": [ + { + "artifact": "bin", + "bin_name": "a-name", + "extern_name": "a_name", + "kind": null, + "target": null + }, + { + "artifact": "bin", + "bin_name": "b-name", + "extern_name": "b_name", + "kind": "dev", + "target": null + }, + { + "artifact": "bin", + "bin_name": "a-name", + "compile_target": "wasm32-unknown-unknown", + "extern_name": "a_name", + "kind": "build", + "target": null + }, + { + "artifact": "bin", + "bin_name": "b-name", + "compile_target": "wasm32-unknown-unknown", + "extern_name": "b_name", + "kind": "build", + "target": null + } + ], + "name": "", + "pkg": "path+[ROOTURL]/foo/bin-only-artifact#0.5.0" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + }, + { + "kind": "dev", + "target": null + }, + { + "kind": "build", + "target": null + } + ], + "name": "non_artifact", + "pkg": "path+[ROOTURL]/foo/non-artifact#0.5.0" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo/bar#0.5.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/bin-only-artifact#0.5.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/non-artifact#0.5.0" + } + ], + "root": null + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/artifact#0.5.0", + "path+[ROOTURL]/foo/bin-only-artifact#0.5.0", + "path+[ROOTURL]/foo/non-artifact#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/artifact#0.5.0", + "path+[ROOTURL]/foo/bin-only-artifact#0.5.0", + "path+[ROOTURL]/foo/non-artifact#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_with_invalid_manifest() { + let p = project().file("Cargo.toml", "").build(); + + p.cargo("metadata --format-version 1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + manifest is missing either a `[package]` or a `[workspace]` + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_with_invalid_authors_field() { + let p = project() + .file("src/foo.rs", "") + .file( + "Cargo.toml", + r#" + [package] + authors = "" + "#, + ) + .build(); + + p.cargo("metadata") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: string "", expected a vector of strings or workspace + --> Cargo.toml:3:27 + | +3 | authors = "" + | ^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_with_invalid_version_field() { + let p = project() + .file("src/foo.rs", "") + .file( + "Cargo.toml", + r#" + [package] + version = 1 + "#, + ) + .build(); + + p.cargo("metadata") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: integer `1`, expected SemVer version + --> Cargo.toml:3:27 + | +3 | version = 1 + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_with_invalid_publish_field() { + let p = project() + .file("src/foo.rs", "") + .file( + "Cargo.toml", + r#" + [package] + publish = "foo" + "#, + ) + .build(); + + p.cargo("metadata") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid type: string "foo", expected a boolean, a vector of strings, or workspace + --> Cargo.toml:3:27 + | +3 | publish = "foo" + | ^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_with_invalid_artifact_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + + [dependencies] + artifact = { path = "artifact", artifact = "bin:notfound" } + "#, + ) + .file("src/lib.rs", "") + .file("artifact/Cargo.toml", &basic_bin_manifest("artifact")) + .file("artifact/src/main.rs", "fn main() {}") + .build(); + + p.cargo("metadata -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems +[LOCKING] 1 package to latest compatible version +[ERROR] dependency `artifact` in package `foo` requires a `bin:notfound` artifact to be present. + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_with_invalid_duplicate_renamed_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + + [dependencies] + bar = { path = "bar" } + baz = { path = "bar", package = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("metadata") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems +[LOCKING] 1 package to latest compatible version +[ERROR] the crate `foo v0.5.0 ([ROOT]/foo)` depends on crate `bar v0.5.0 ([ROOT]/foo/bar)` multiple times with different names + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_no_deps_path_to_cargo_toml_relative() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("metadata --no-deps --manifest-path foo/Cargo.toml") + .cwd(p.root().parent().unwrap()) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/foo.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_no_deps_path_to_cargo_toml_absolute() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("metadata --no-deps --manifest-path") + .arg(p.root().join("Cargo.toml")) + .cwd(p.root().parent().unwrap()) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/foo.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_no_deps_path_to_cargo_toml_parent_relative() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("metadata --no-deps --manifest-path foo") + .cwd(p.root().parent().unwrap()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the manifest-path must be a path to a Cargo.toml file + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_no_deps_path_to_cargo_toml_parent_absolute() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("metadata --no-deps --manifest-path") + .arg(p.root()) + .cwd(p.root().parent().unwrap()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the manifest-path must be a path to a Cargo.toml file + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_metadata_no_deps_cwd() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("metadata --no-deps") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/foo.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_bad_version() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("metadata --no-deps --format-version 2") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] invalid value '2' for '--format-version ' + [possible values: 1] + +... +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [features] + a = [] + b = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("metadata --features").arg("a b").run(); +} + +#[cargo_test] +fn package_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = ["wycats@example.com"] + categories = ["database"] + keywords = ["database"] + readme = "README.md" + repository = "https://github.com/rust-lang/cargo" + homepage = "https://rust-lang.org" + documentation = "https://doc.rust-lang.org/stable/std/" + + [package.metadata.bar] + baz = "quux" + "#, + ) + .file("README.md", "") + .file("src/lib.rs", "") + .build(); + + p.cargo("metadata --no-deps") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [ + "database" + ], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": "https://doc.rust-lang.org/stable/std/", + "edition": "2015", + "features": {}, + "homepage": "https://rust-lang.org", + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [ + "database" + ], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": { + "bar": { + "baz": "quux" + } + }, + "name": "foo", + "publish": null, + "readme": "README.md", + "repository": "https://github.com/rust-lang/cargo", + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.1.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn package_publish() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = ["wycats@example.com"] + categories = ["database"] + keywords = ["database"] + readme = "README.md" + repository = "https://github.com/rust-lang/cargo" + publish = ["my-registry"] + "#, + ) + .file("README.md", "") + .file("src/lib.rs", "") + .build(); + + p.cargo("metadata --no-deps") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [ + "database" + ], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [ + "database" + ], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": [ + "my-registry" + ], + "readme": "README.md", + "repository": "https://github.com/rust-lang/cargo", + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.1.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_metadata_path_to_cargo_toml_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("package --manifest-path") + .arg(p.root().join("bar/Cargo.toml")) + .cwd(p.root().parent().unwrap()) + .run(); + + p.cargo("metadata --manifest-path") + .arg(p.root().join("target/package/bar-0.5.0/Cargo.toml")) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/target/package/bar-0.5.0/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/foo/target/package/bar-0.5.0/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0" + } + ], + "root": "path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0" + }, + "target_directory": "[ROOT]/foo/target/package/bar-0.5.0/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/target/package/bar-0.5.0#bar@0.5.0" + ], + "workspace_root": "[ROOT]/foo/target/package/bar-0.5.0" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn package_edition_2018() { + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = ["wycats@example.com"] + edition = "2018" + "#, + ) + .build(); + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2018", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2018", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.1.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn package_default_run() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", r#"fn main() { println!("hello A"); }"#) + .file("src/bin/b.rs", r#"fn main() { println!("hello B"); }"#) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = ["wycats@example.com"] + edition = "2018" + default-run = "a" + "#, + ) + .build(); + let json = p.cargo("metadata").run_json(); + assert_eq!(json["packages"][0]["default_run"], json!("a")); +} + +#[cargo_test] +fn package_rust_version() { + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = ["wycats@example.com"] + edition = "2018" + rust-version = "1.56" + "#, + ) + .build(); + let json = p.cargo("metadata").run_json(); + assert_eq!(json["packages"][0]["rust_version"], json!("1.56")); +} + +#[cargo_test] +fn target_edition_2018() { + let p = project() + .file("src/lib.rs", "") + .file("src/main.rs", "") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = ["wycats@example.com"] + edition = "2015" + + [lib] + edition = "2018" + "#, + ) + .build(); + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2018", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/main.rs", + "test": true + } + ], + "version": "0.1.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn rename_dependency() { + 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.0.1" + authors = [] + + [dependencies] + bar = { version = "0.1.0" } + baz = { version = "0.2.0", package = "bar" } + "#, + ) + .file("src/lib.rs", "extern crate bar; extern crate baz;") + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.1.0/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.1.0/src/lib.rs", + "test": true + } + ], + "version": "0.1.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.2.0/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.2.0/src/lib.rs", + "test": true + } + ], + "version": "0.2.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "bar", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.1.0", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "bar", + "optional": false, + "registry": null, + "rename": "baz", + "req": "^0.2.0", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0", + "registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "bar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "baz", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.2.0" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.0.1" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.0.1" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn metadata_links() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + links = "a" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": "a", + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": false, + "doctest": false, + "edition": "2015", + "kind": [ + "custom-build" + ], + "name": "build-script-build", + "src_path": "[ROOT]/foo/build.rs", + "test": false + } + ], + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.5.0" + } + ], + "root": "path+[ROOTURL]/foo#0.5.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn deps_with_bin_only() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [dependencies] + bdep = { path = "bdep" } + "#, + ) + .file("src/lib.rs", "") + .file("bdep/Cargo.toml", &basic_bin_manifest("bdep")) + .file("bdep/src/main.rs", "fn main() {}") + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "bdep", + "optional": false, + "path": "[ROOT]/foo/bdep", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.1.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.1.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn filter_platform() { + // Testing the --filter-platform flag. + Package::new("normal-dep", "0.0.1").publish(); + Package::new("host-dep", "0.0.1").publish(); + Package::new("alt-dep", "0.0.1").publish(); + Package::new("cfg-dep", "0.0.1").publish(); + // Just needs to be a valid target that is different from host. + // Presumably nobody runs these tests on wasm. 🙃 + let alt_target = "wasm32-unknown-unknown"; + let host_target = rustc_host(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + normal-dep = "0.0.1" + + [target.{}.dependencies] + host-dep = "0.0.1" + + [target.{}.dependencies] + alt-dep = "0.0.1" + + [target.'cfg(foobar)'.dependencies] + cfg-dep = "0.0.1" + "#, + host_target, alt_target + ), + ) + .file("src/lib.rs", "") + .build(); + + // We're going to be checking that we don't download excessively, + // so we need to ensure that downloads will happen. + let clear = || { + paths::cargo_home().join("registry/cache").rm_rf(); + paths::cargo_home().join("registry/src").rm_rf(); + p.build_dir().rm_rf(); + }; + + // Normal metadata, no filtering, returns *everything*. + p.cargo("metadata") + .with_stderr_data( + str![[r#" +[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems +[UPDATING] `dummy-registry` index +[LOCKING] 4 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] cfg-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] alt-dep v0.0.1 (registry `dummy-registry`) + +"#]] + .unordered(), + ) + .with_stdout_data( + str![[r#" +{ + "packages": [ + { + "name": "alt-dep", + "dependencies": [], + "...": "{...}" + }, + { + "name": "cfg-dep", + "dependencies": [], + "...": "{...}" + }, + { + "name": "foo", + "dependencies": [ + { + "name": "normal-dep", + "target": null, + "...": "{...}" + }, + { + "name": "cfg-dep", + "target": "cfg(foobar)", + "...": "{...}" + }, + { + "name": "alt-dep", + "target": "wasm32-unknown-unknown", + "...": "{...}" + }, + { + "name": "host-dep", + "target": "[HOST_TARGET]", + "...": "{...}" + } + ], + "...": "{...}" + }, + { + "name": "host-dep", + "dependencies": [], + "...": "{...}" + }, + { + "name": "normal-dep", + "dependencies": [], + "...": "{...}" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": "wasm32-unknown-unknown" + } + ], + "name": "alt_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": "cfg(foobar)" + } + ], + "name": "cfg_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": "[HOST_TARGET]" + } + ], + "name": "host_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "normal_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "...": "{...}" +} +"#]] + .is_json() + .unordered(), + ) + .run(); + clear(); + + // Filter on alternate, removes cfg and host. + p.cargo("metadata --filter-platform") + .arg(alt_target) + .with_stderr_data( + str![[r#" +[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems +[DOWNLOADING] crates ... +[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] alt-dep v0.0.1 (registry `dummy-registry`) + +"#]] + .unordered(), + ) + .with_stdout_data( + str![[r#" +{ + "packages": [ + { + "name": "alt-dep", + "dependencies": [], + "...": "{...}" + }, + { + "name": "foo", + "dependencies": [ + { + "name": "normal-dep", + "target": null, + "...": "{...}" + }, + { + "name": "cfg-dep", + "target": "cfg(foobar)", + "...": "{...}" + }, + { + "name": "alt-dep", + "target": "wasm32-unknown-unknown", + "...": "{...}" + }, + { + "name": "host-dep", + "target": "[HOST_TARGET]", + "...": "{...}" + } + ], + "...": "{...}" + }, + { + "name": "normal-dep", + "dependencies": [], + "...": "{...}" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": "wasm32-unknown-unknown" + } + ], + "name": "alt_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#alt-dep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "normal_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "...": "{...}" +} +"#]] + .is_json() + .unordered(), + ) + .run(); + clear(); + + // Filter on host, removes alt and cfg. + p.cargo("metadata --filter-platform") + .arg(&host_target) + .with_stderr_data( + str![[r#" +[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems +[DOWNLOADING] crates ... +[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`) + +"#]] + .unordered(), + ) + .with_stdout_data( + str![[r#" +{ + "packages": [ + { + "name": "foo", + "dependencies": [ + { + "name": "normal-dep", + "target": null, + "...": "{...}" + }, + { + "name": "cfg-dep", + "target": "cfg(foobar)", + "...": "{...}" + }, + { + "name": "alt-dep", + "target": "wasm32-unknown-unknown", + "...": "{...}" + }, + { + "name": "host-dep", + "target": "[HOST_TARGET]", + "...": "{...}" + } + ], + "...": "{...}" + }, + { + "name": "host-dep", + "dependencies": [], + "...": "{...}" + }, + { + "name": "normal-dep", + "dependencies": [], + "...": "{...}" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": "[HOST_TARGET]" + } + ], + "name": "host_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "normal_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "...": "{...}" +} +"#]] + .is_json() + .unordered(), + ) + .run(); + clear(); + + // Filter host with cfg, removes alt only + p.cargo("metadata --filter-platform") + .arg(&host_target) + .env("RUSTFLAGS", "--cfg=foobar") + .with_stderr_data( + str![[r#" +[WARNING] please specify `--format-version` flag explicitly to avoid compatibility problems +[DOWNLOADING] crates ... +[DOWNLOADED] normal-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] host-dep v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] cfg-dep v0.0.1 (registry `dummy-registry`) + +"#]] + .unordered(), + ) + .with_stdout_data( + str![[r#" +{ + "packages": [ + { + "name": "cfg-dep", + "dependencies": [], + "...": "{...}" + }, + { + "name": "foo", + "dependencies": [ + { + "name": "normal-dep", + "target": null, + "...": "{...}" + }, + { + "name": "cfg-dep", + "target": "cfg(foobar)", + "...": "{...}" + }, + { + "name": "alt-dep", + "target": "wasm32-unknown-unknown", + "...": "{...}" + }, + { + "name": "host-dep", + "target": "[HOST_TARGET]", + "...": "{...}" + } + ], + "...": "{...}" + }, + { + "name": "host-dep", + "dependencies": [], + "...": "{...}" + }, + { + "name": "normal-dep", + "dependencies": [], + "...": "{...}" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1", + "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": "cfg(foobar)" + } + ], + "name": "cfg_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#cfg-dep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": "[HOST_TARGET]" + } + ], + "name": "host_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "normal_dep", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#host-dep@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#normal-dep@0.0.1" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "...": "{...}" +} +"#]] + .is_json() + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn dep_kinds() { + Package::new("bar", "0.1.0").publish(); + Package::new("winapi", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "0.1" + + [dev-dependencies] + bar = "0.1" + + [build-dependencies] + bar = "0.1" + + [target.'cfg(windows)'.dependencies] + winapi = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": "{...}", + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0", + "registry+https://github.com/rust-lang/crates.io-index#winapi@0.1.0" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + }, + { + "kind": "dev", + "target": null + }, + { + "kind": "build", + "target": null + } + ], + "name": "bar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": "cfg(windows)" + } + ], + "name": "winapi", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#winapi@0.1.0" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#0.1.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#winapi@0.1.0" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn dep_kinds_workspace() { + // Check for bug with duplicate dep kinds in a workspace. + // If different members select different features for the same package, + // they show up multiple times in the resolver `deps`. + // + // Here: + // foo -> dep + // bar -> foo[feat1] -> dep + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [features] + feat1 = [] + + [dependencies] + dep = { path="dep" } + + [workspace] + members = ["bar"] + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + + [dependencies] + foo = { path="..", features=["feat1"] } + "#, + ) + .file("bar/src/lib.rs", "") + .file("dep/Cargo.toml", &basic_lib_manifest("dep")) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": "{...}", + "resolve": { + "nodes": [ + { + "dependencies": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "foo", + "pkg": "path+[ROOTURL]/foo#0.1.0" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo/bar#0.1.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/dep#0.5.0" + }, + { + "dependencies": [ + "path+[ROOTURL]/foo/dep#0.5.0" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "dep", + "pkg": "path+[ROOTURL]/foo/dep#0.5.0" + } + ], + "features": [ + "feat1" + ], + "id": "path+[ROOTURL]/foo#0.1.0" + } + ], + "root": "path+[ROOTURL]/foo#0.1.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.1.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/bar#0.1.0", + "path+[ROOTURL]/foo#0.1.0", + "path+[ROOTURL]/foo/dep#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +// Creating non-utf8 path is an OS-specific pain, so let's run this only on +// linux, where arbitrary bytes work. +#[cfg(target_os = "linux")] +#[cargo_test] +fn cargo_metadata_non_utf8() { + use std::ffi::OsString; + use std::os::unix::ffi::OsStringExt; + use std::path::PathBuf; + + let base = PathBuf::from(OsString::from_vec(vec![255])); + + let p = project() + .no_manifest() + .file(base.join("./src/lib.rs"), "") + .file(base.join("./Cargo.toml"), &basic_lib_manifest("foo")) + .build(); + + p.cargo("metadata") + .cwd(p.root().join(base)) + .arg("--format-version") + .arg("1") + .with_stderr_data(str![[r#" +[ERROR] path contains invalid UTF-8 characters + +"#]]) + .with_status(101) + .run(); +} + +// TODO: Consider using this test instead of the version without the 'artifact' suffix or merge them because they should be pretty much the same. +#[cargo_test] +fn workspace_metadata_with_dependencies_no_deps_artifact() { + let p = project() + // NOTE that 'artifact' isn't mentioned in the workspace here, yet it shows up as member. + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + baz = { path = "../baz/" } + baz-renamed = { path = "../baz/" } + artifact = { path = "../artifact/", artifact = "bin" } + "#, + ) + .file("bar/src/lib.rs", "") + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file("baz/src/lib.rs", "") + .file("artifact/Cargo.toml", &basic_bin_manifest("artifact")) + .file("artifact/src/main.rs", "fn main() {}") + .build(); + + p.cargo("metadata --no-deps -Z bindeps") + .masquerade_as_nightly_cargo(&["bindeps"]) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [ + { + "artifact": { + "kinds": [ + "bin" + ], + "lib": false, + "target": null + }, + "features": [], + "kind": null, + "name": "artifact", + "optional": false, + "path": "[ROOT]/foo/artifact", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "baz", + "optional": false, + "path": "[ROOT]/foo/baz", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "baz-renamed", + "optional": false, + "path": "[ROOT]/foo/baz", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/bar#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/bar/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/foo/bar/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/artifact#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/artifact/Cargo.toml", + "metadata": null, + "name": "artifact", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "artifact", + "src_path": "[ROOT]/foo/artifact/src/main.rs", + "test": true + } + ], + "version": "0.5.0" + }, + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/baz#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/baz/Cargo.toml", + "metadata": null, + "name": "baz", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "baz", + "src_path": "[ROOT]/foo/baz/src/lib.rs", + "test": true + } + ], + "version": "0.5.0" + } + ], + "resolve": null, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/artifact#0.5.0", + "path+[ROOTURL]/foo/baz#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/bar#0.5.0", + "path+[ROOTURL]/foo/artifact#0.5.0", + "path+[ROOTURL]/foo/baz#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn versionless_packages() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + + [dependencies] + foobar = "0.0.1" + baz = { path = "../baz/" } + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + + [dependencies] + foobar = "0.0.1" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + Package::new("foobar", "0.0.1").publish(); + + p.cargo("metadata -q --format-version 1") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "baz", + "optional": false, + "path": "[ROOT]/foo/baz", + "registry": null, + "rename": null, + "req": "*", + "source": null, + "target": null, + "uses_default_features": true + }, + { + "features": [], + "kind": null, + "name": "foobar", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.0.1", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/bar#0.0.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/bar/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": [], + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/foo/bar/src/lib.rs", + "test": true + } + ], + "version": "0.0.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "foobar", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.0.1", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/baz#0.0.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/baz/Cargo.toml", + "metadata": null, + "name": "baz", + "publish": [], + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "baz", + "src_path": "[ROOT]/foo/baz/src/lib.rs", + "test": true + } + ], + "version": "0.0.0" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/Cargo.toml", + "metadata": null, + "name": "foobar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foobar", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/foobar-0.0.1/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [ + "path+[ROOTURL]/foo/baz#0.0.0", + "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "baz", + "pkg": "path+[ROOTURL]/foo/baz#0.0.0" + }, + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "foobar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo/bar#0.0.0" + }, + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "foobar", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo/baz#0.0.0" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#foobar@0.0.1" + } + ], + "root": null + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo/bar#0.0.0", + "path+[ROOTURL]/foo/baz#0.0.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/bar#0.0.0", + "path+[ROOTURL]/foo/baz#0.0.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} + +/// Record how TOML-specific types are deserialized by `toml` so we can make sure we know if these change and +/// can have a conversation about what should be done. +#[cargo_test] +fn cargo_metadata_toml_types() { + let p = project() + .file("src/lib.rs", "") + .file( + "Cargo.toml", + " +[package] +name = 'foo' +edition = '2015' + +[package.metadata] +offset-datetime = 1979-05-27T07:32:00Z +local-datetime = 1979-05-27T07:32:00 +local-date = 1979-05-27 +local-time = 1979-05-27 +", + ) + .build(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.0.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": { + "local-date": { + "$__toml_private_datetime": "1979-05-27" + }, + "local-datetime": { + "$__toml_private_datetime": "1979-05-27T07:32:00" + }, + "local-time": { + "$__toml_private_datetime": "1979-05-27" + }, + "offset-datetime": { + "$__toml_private_datetime": "1979-05-27T07:32:00Z" + } + }, + "name": "foo", + "publish": [], + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.0.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.0.0" + } + ], + "root": "path+[ROOTURL]/foo#0.0.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.0.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.0.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/minimal_versions.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/minimal_versions.rs new file mode 100644 index 000000000..ef565b0f6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/minimal_versions.rs @@ -0,0 +1,46 @@ +//! Tests for minimal-version resolution. +//! +//! Note: Some tests are located in the resolver-tests package. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +// Ensure that the "-Z minimal-versions" CLI option works and the minimal +// version of a dependency ends up in the lock file. +#[cargo_test] +fn minimal_version_cli() { + Package::new("dep", "1.0.0").publish(); + Package::new("dep", "1.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.1" + + [dependencies] + dep = "1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile -Zminimal-versions") + .masquerade_as_nightly_cargo(&["minimal-versions"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to earliest compatible version +[ADDING] dep v1.0.0 (available: v1.1.0) + +"#]]) + .run(); + + let lock = p.read_lockfile(); + + assert!(!lock.contains("1.1.0")); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/multitarget.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/multitarget.rs new file mode 100644 index 000000000..f159a3ecb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/multitarget.rs @@ -0,0 +1,270 @@ +//! Tests for multiple `--target` flags to subcommands + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, cross_compile, project, rustc_host, str}; + +#[cargo_test] +fn simple_build() { + if cross_compile::disabled() { + return; + } + let t1 = cross_compile::alternate(); + let t2 = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .arg("--target") + .arg(&t1) + .arg("--target") + .arg(&t2) + .run(); + + assert!(p.target_bin(t1, "foo").is_file()); + assert!(p.target_bin(t2, "foo").is_file()); +} + +#[cargo_test] +fn simple_build_with_config() { + if cross_compile::disabled() { + return; + } + let t1 = cross_compile::alternate(); + let t2 = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + &format!( + r#" + [build] + target = ["{t1}", "{t2}"] + "# + ), + ) + .build(); + + p.cargo("build").run(); + + assert!(p.target_bin(t1, "foo").is_file()); + assert!(p.target_bin(t2, "foo").is_file()); +} + +#[cargo_test] +fn simple_test() { + if !cross_compile::can_run_on_host() { + return; + } + let t1 = cross_compile::alternate(); + let t2 = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/lib.rs", "fn main() {}") + .build(); + + p.cargo("test") + .arg("--target") + .arg(&t1) + .arg("--target") + .arg(&t2) + .with_stderr_data( + str![[r#" +[RUNNING] unittests src/lib.rs (target/[ALT_TARGET]/debug/deps/foo-[HASH][EXE]) +[RUNNING] unittests src/lib.rs (target/[HOST_TARGET]/debug/deps/foo-[HASH][EXE]) +... + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn simple_run() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("run --target a --target b") + .with_stderr_data(str![[r#" +[ERROR] only one `--target` argument is supported + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn simple_doc() { + if cross_compile::disabled() { + return; + } + let t1 = cross_compile::alternate(); + let t2 = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/lib.rs", "//! empty lib") + .build(); + + p.cargo("doc") + .arg("--target") + .arg(&t1) + .arg("--target") + .arg(&t2) + .run(); + + assert!(p.build_dir().join(&t1).join("doc/foo/index.html").is_file()); + assert!(p.build_dir().join(&t2).join("doc/foo/index.html").is_file()); +} + +#[cargo_test] +fn simple_doc_open() { + if cross_compile::disabled() { + return; + } + let t1 = cross_compile::alternate(); + let t2 = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/lib.rs", "//! empty lib") + .build(); + + p.cargo("doc") + .arg("--open") + .arg("--target") + .arg(&t1) + .arg("--target") + .arg(&t2) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v1.0.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[ERROR] only one `--target` argument is supported + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn simple_check() { + if cross_compile::disabled() { + return; + } + let t1 = cross_compile::alternate(); + let t2 = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .arg("--target") + .arg(&t1) + .arg("--target") + .arg(&t2) + .run(); +} + +#[cargo_test] +fn same_value_twice() { + if cross_compile::disabled() { + return; + } + let t = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .arg("--target") + .arg(&t) + .arg("--target") + .arg(&t) + .run(); + + assert!(p.target_bin(t, "foo").is_file()); +} + +#[cargo_test] +fn same_value_twice_with_config() { + if cross_compile::disabled() { + return; + } + let t = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + &format!( + r#" + [build] + target = ["{t}", "{t}"] + "# + ), + ) + .build(); + + p.cargo("build").run(); + + assert!(p.target_bin(t, "foo").is_file()); +} + +#[cargo_test] +fn works_with_config_in_both_string_or_list() { + if cross_compile::disabled() { + return; + } + let t = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + &format!( + r#" + [build] + target = "{t}" + "# + ), + ) + .build(); + + p.cargo("build").run(); + + assert!(p.target_bin(t, "foo").is_file()); + + p.cargo("clean").run(); + + p.change_file( + ".cargo/config.toml", + &format!( + r#" + [build] + target = ["{t}"] + "# + ), + ); + + p.cargo("build").run(); + + assert!(p.target_bin(t, "foo").is_file()); +} + +#[cargo_test] +fn works_with_env() { + let t = rustc_host(); + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build").env("CARGO_BUILD_TARGET", t).run(); + + assert!(p.target_bin(t, "foo").is_file()); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/net_config.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/net_config.rs new file mode 100644 index 000000000..b765678c7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/net_config.rs @@ -0,0 +1,78 @@ +//! Tests for network configuration. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn net_retry_loads_from_config() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies.bar] + git = "http://127.0.0.1:11/foo/bar" + "#, + ) + .file("src/main.rs", "") + .file( + ".cargo/config.toml", + r#" + [net] + retry=1 + [http] + timeout=1 + "#, + ) + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +... +[WARNING] spurious network error (1 tries remaining): [..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn net_retry_git_outputs_warning() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies.bar] + git = "http://127.0.0.1:11/foo/bar" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [http] + timeout=1 + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check -v -j 1") + .with_status(101) + .with_stderr_data(str![[r#" +... +[WARNING] spurious network error (2 tries remaining): [..] +[WARNING] spurious network error (1 tries remaining): [..] +... +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/new.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/new.rs new file mode 100644 index 000000000..8a57283fc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/new.rs @@ -0,0 +1,571 @@ +//! Tests for the `cargo new` command. + +use std::env; +use std::fs::{self, File}; + +use cargo_test_support::cargo_process; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::str; + +fn create_default_gitconfig() { + // This helps on Windows where libgit2 is very aggressive in attempting to + // find a git config file. + let gitconfig = paths::home().join(".gitconfig"); + File::create(gitconfig).unwrap(); + + // If we're running this under a user account that has a different default branch set up + // then tests that assume the default branch is master will fail. We set the default branch + // to master explicitly so that tests that rely on this behavior still pass. + fs::write( + paths::home().join(".gitconfig"), + r#" + [init] + defaultBranch = master + "#, + ) + .unwrap(); +} + +#[cargo_test] +fn simple_lib() { + cargo_process("new --lib foo --vcs none --edition 2015") + .with_stderr_data(str![[r#" +[CREATING] library `foo` package +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]) + .run(); + + assert!(paths::root().join("foo").is_dir()); + assert!(paths::root().join("foo/Cargo.toml").is_file()); + assert!(paths::root().join("foo/src/lib.rs").is_file()); + assert!(!paths::root().join("foo/.gitignore").is_file()); + + let lib = paths::root().join("foo/src/lib.rs"); + let contents = fs::read_to_string(&lib).unwrap(); + assert_eq!( + contents, + r#"pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} +"# + ); + + cargo_process("build").cwd(&paths::root().join("foo")).run(); +} + +#[cargo_test] +fn simple_bin() { + cargo_process("new --bin foo --edition 2015") + .with_stderr_data(str![[r#" +[CREATING] binary (application) `foo` package +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]) + .run(); + + assert!(paths::root().join("foo").is_dir()); + assert!(paths::root().join("foo/Cargo.toml").is_file()); + assert!(paths::root().join("foo/src/main.rs").is_file()); + + cargo_process("build").cwd(&paths::root().join("foo")).run(); + assert!(paths::root() + .join(&format!("foo/target/debug/foo{}", env::consts::EXE_SUFFIX)) + .is_file()); +} + +#[cargo_test] +fn both_lib_and_bin() { + cargo_process("new --lib --bin foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] can't specify both lib and binary outputs + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_git() { + cargo_process("new --lib foo --edition 2015").run(); + + assert!(paths::root().is_dir()); + assert!(paths::root().join("foo/Cargo.toml").is_file()); + assert!(paths::root().join("foo/src/lib.rs").is_file()); + assert!(paths::root().join("foo/.git").is_dir()); + assert!(paths::root().join("foo/.gitignore").is_file()); + + let fp = paths::root().join("foo/.gitignore"); + let contents = fs::read_to_string(&fp).unwrap(); + assert_eq!(contents, "/target\n",); + + cargo_process("build").cwd(&paths::root().join("foo")).run(); +} + +#[cargo_test(requires = "hg")] +fn simple_hg() { + cargo_process("new --lib foo --edition 2015 --vcs hg").run(); + + assert!(paths::root().is_dir()); + assert!(paths::root().join("foo/Cargo.toml").is_file()); + assert!(paths::root().join("foo/src/lib.rs").is_file()); + assert!(paths::root().join("foo/.hg").is_dir()); + assert!(paths::root().join("foo/.hgignore").is_file()); + + let fp = paths::root().join("foo/.hgignore"); + let contents = fs::read_to_string(&fp).unwrap(); + assert_eq!(contents, "^target$\n",); + + cargo_process("build").cwd(&paths::root().join("foo")).run(); +} + +#[cargo_test] +fn no_argument() { + cargo_process("new") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the following required arguments were not provided: + +... +"#]]) + .run(); +} + +#[cargo_test] +fn existing() { + let dst = paths::root().join("foo"); + fs::create_dir(&dst).unwrap(); + cargo_process("new foo") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `foo` package +[ERROR] destination `[ROOT]/foo` already exists + +Use `cargo init` to initialize the directory + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_characters() { + cargo_process("new foo.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `foo.rs` package +[ERROR] invalid character `.` in package name: `foo.rs`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) +If you need a package name to not match the directory name, consider using --name flag. +If you need a binary with the name "foo.rs", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/foo.rs.rs` or change the name in Cargo.toml with: + + [[bin]] + name = "foo.rs" + path = "src/main.rs" + + +"#]]) + .run(); +} + +#[cargo_test] +fn reserved_name() { + cargo_process("new test") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `test` package +[ERROR] the name `test` cannot be used as a package name, it conflicts with Rust's built-in test library +If you need a package name to not match the directory name, consider using --name flag. +If you need a binary with the name "test", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/test.rs` or change the name in Cargo.toml with: + + [[bin]] + name = "test" + path = "src/main.rs" + + +"#]]) + .run(); +} + +#[cargo_test] +fn reserved_binary_name() { + cargo_process("new --bin incremental") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `incremental` package +[ERROR] the name `incremental` cannot be used as a package name, it conflicts with cargo's build directory names +If you need a package name to not match the directory name, consider using --name flag. + +"#]]) + .run(); + + cargo_process("new --lib incremental") + .with_stderr_data(str![[r#" +[CREATING] library `incremental` package +[WARNING] the name `incremental` will not support binary executables with that name, it conflicts with cargo's build directory names +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]) + .run(); +} + +#[cargo_test] +fn keyword_name() { + cargo_process("new pub") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `pub` package +[ERROR] the name `pub` cannot be used as a package name, it is a Rust keyword +If you need a package name to not match the directory name, consider using --name flag. +If you need a binary with the name "pub", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/pub.rs` or change the name in Cargo.toml with: + + [[bin]] + name = "pub" + path = "src/main.rs" + + +"#]]) + .run(); +} + +#[cargo_test] +fn std_name() { + cargo_process("new core").with_stderr_data(str![[r#" +[CREATING] binary (application) `core` package +[WARNING] the name `core` is part of Rust's standard library +It is recommended to use a different name to avoid problems. +If you need a package name to not match the directory name, consider using --name flag. +If you need a binary with the name "core", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/core.rs` or change the name in Cargo.toml with: + + [[bin]] + name = "core" + path = "src/main.rs" + +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]).run(); +} + +#[cargo_test] +fn git_prefers_command_line() { + let root = paths::root(); + fs::create_dir(&root.join(".cargo")).unwrap(); + fs::write( + &root.join(".cargo/config.toml"), + r#" + [cargo-new] + vcs = "none" + name = "foo" + email = "bar" + "#, + ) + .unwrap(); + + cargo_process("new foo --vcs git").run(); + assert!(paths::root().join("foo/.gitignore").exists()); + assert!(!fs::read_to_string(paths::root().join("foo/Cargo.toml")) + .unwrap() + .contains("authors =")); +} + +#[cargo_test] +fn subpackage_no_git() { + cargo_process("new foo").run(); + + assert!(paths::root().join("foo/.git").is_dir()); + assert!(paths::root().join("foo/.gitignore").is_file()); + + let subpackage = paths::root().join("foo").join("components"); + fs::create_dir(&subpackage).unwrap(); + cargo_process("new foo/components/subcomponent").run(); + + assert!(!paths::root() + .join("foo/components/subcomponent/.git") + .is_file()); + assert!(!paths::root() + .join("foo/components/subcomponent/.gitignore") + .is_file()); +} + +#[cargo_test] +fn subpackage_git_with_gitignore() { + cargo_process("new foo").run(); + + assert!(paths::root().join("foo/.git").is_dir()); + assert!(paths::root().join("foo/.gitignore").is_file()); + + let gitignore = paths::root().join("foo/.gitignore"); + fs::write(gitignore, b"components").unwrap(); + + let subpackage = paths::root().join("foo/components"); + fs::create_dir(&subpackage).unwrap(); + cargo_process("new foo/components/subcomponent").run(); + + assert!(paths::root() + .join("foo/components/subcomponent/.git") + .is_dir()); + assert!(paths::root() + .join("foo/components/subcomponent/.gitignore") + .is_file()); +} + +#[cargo_test] +fn subpackage_git_with_vcs_arg() { + cargo_process("new foo").run(); + + let subpackage = paths::root().join("foo").join("components"); + fs::create_dir(&subpackage).unwrap(); + cargo_process("new foo/components/subcomponent --vcs git").run(); + + assert!(paths::root() + .join("foo/components/subcomponent/.git") + .is_dir()); + assert!(paths::root() + .join("foo/components/subcomponent/.gitignore") + .is_file()); +} + +#[cargo_test] +fn unknown_flags() { + cargo_process("new foo --flag") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '--flag' found +... +"#]]) + .run(); +} + +#[cargo_test] +fn explicit_invalid_name_not_suggested() { + cargo_process("new --name 10-invalid a") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `10-invalid` package +[ERROR] invalid character `1` in package name: `10-invalid`, the name cannot start with a digit +If you need a binary with the name "10-invalid", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/10-invalid.rs` or change the name in Cargo.toml with: + + [[bin]] + name = "10-invalid" + path = "src/main.rs" + + +"#]]) + .run(); +} + +#[cargo_test] +fn explicit_project_name() { + cargo_process("new --lib foo --name bar") + .with_stderr_data(str![[r#" +[CREATING] library `bar` package +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]) + .run(); +} + +#[cargo_test] +fn new_with_edition_2015() { + cargo_process("new --edition 2015 foo").run(); + let manifest = fs::read_to_string(paths::root().join("foo/Cargo.toml")).unwrap(); + assert!(manifest.contains("edition = \"2015\"")); +} + +#[cargo_test] +fn new_with_edition_2018() { + cargo_process("new --edition 2018 foo").run(); + let manifest = fs::read_to_string(paths::root().join("foo/Cargo.toml")).unwrap(); + assert!(manifest.contains("edition = \"2018\"")); +} + +#[cargo_test] +fn new_default_edition() { + cargo_process("new foo").run(); + let manifest = fs::read_to_string(paths::root().join("foo/Cargo.toml")).unwrap(); + assert!(manifest.contains("edition = \"2024\"")); +} + +#[cargo_test] +fn new_with_bad_edition() { + cargo_process("new --edition something_else foo") + .with_stderr_data(str![[r#" +[ERROR] invalid value 'something_else' for '--edition ' +... +"#]]) + .with_status(1) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn lockfile_constant_during_new() { + cargo_process("new foo").run(); + + cargo_process("build").cwd(&paths::root().join("foo")).run(); + let before = fs::read_to_string(paths::root().join("foo/Cargo.lock")).unwrap(); + cargo_process("build").cwd(&paths::root().join("foo")).run(); + let after = fs::read_to_string(paths::root().join("foo/Cargo.lock")).unwrap(); + assert_eq!(before, after); +} + +#[cargo_test] +fn restricted_windows_name() { + if cfg!(windows) { + cargo_process("new nul") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `nul` package +[ERROR] cannot use name `nul`, it is a reserved Windows filename +If you need a package name to not match the directory name, consider using --name flag. + +"#]]) + .run(); + } else { + cargo_process("new nul").with_stderr_data(str![[r#" +[CREATING] binary (application) `nul` package +[WARNING] the name `nul` is a reserved Windows filename +This package will not work on Windows platforms. +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]).run(); + } +} + +#[cargo_test] +fn non_ascii_name() { + cargo_process("new Привет").with_stderr_data(str![[r#" +[CREATING] binary (application) `Привет` package +[WARNING] the name `Привет` contains non-ASCII characters +Non-ASCII crate names are not supported by Rust. +[WARNING] the name `Привет` is not snake_case or kebab-case which is recommended for package names, consider `привет` +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]).run(); +} + +#[cargo_test] +fn non_ascii_name_invalid() { + // These are alphanumeric characters, but not Unicode XID. + cargo_process("new ⒶⒷⒸ") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `ⒶⒷⒸ` package +[ERROR] invalid character `Ⓐ` in package name: `ⒶⒷⒸ`, the first character must be a Unicode XID start character (most letters or `_`) +If you need a package name to not match the directory name, consider using --name flag. +If you need a binary with the name "ⒶⒷⒸ", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/ⒶⒷⒸ.rs` or change the name in Cargo.toml with: + + [[bin]] + name = "ⒶⒷⒸ" + path = "src/main.rs" + + +"#]]) + .run(); + + cargo_process("new a¼") + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) `a¼` package +[ERROR] invalid character `¼` in package name: `a¼`, characters must be Unicode XID characters (numbers, `-`, `_`, or most letters) +If you need a package name to not match the directory name, consider using --name flag. +If you need a binary with the name "a¼", use a valid package name, and set the binary name to be different from the package. This can be done by setting the binary filename to `src/bin/a¼.rs` or change the name in Cargo.toml with: + + [[bin]] + name = "a¼" + path = "src/main.rs" + + +"#]]) + .run(); +} + +#[cargo_test] +fn non_snake_case_name() { + cargo_process("new UPPERcase_name") + .with_stderr_data(str![[r#" +[CREATING] binary (application) `UPPERcase_name` package +[WARNING] the name `UPPERcase_name` is not snake_case or kebab-case which is recommended for package names, consider `uppercase_name` +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]) + .run(); +} + +#[cargo_test] +fn kebab_case_name_is_accepted() { + cargo_process("new kebab-case-is-valid") + .with_stderr_data(str![[r#" +[CREATING] binary (application) `kebab-case-is-valid` package +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]) + .run(); +} + +#[cargo_test] +fn git_default_branch() { + // Check for init.defaultBranch support. + create_default_gitconfig(); + + cargo_process("new foo").run(); + let repo = git2::Repository::open(paths::root().join("foo")).unwrap(); + let head = repo.find_reference("HEAD").unwrap(); + assert_eq!(head.symbolic_target().unwrap(), "refs/heads/master"); + + fs::write( + paths::home().join(".gitconfig"), + r#" + [init] + defaultBranch = hello + "#, + ) + .unwrap(); + cargo_process("new bar").run(); + let repo = git2::Repository::open(paths::root().join("bar")).unwrap(); + let head = repo.find_reference("HEAD").unwrap(); + assert_eq!(head.symbolic_target().unwrap(), "refs/heads/hello"); +} + +#[cargo_test] +fn non_utf8_str_in_ignore_file() { + let gitignore = paths::home().join(".gitignore"); + File::create(gitignore).unwrap(); + + fs::write(paths::home().join(".gitignore"), &[0xFF, 0xFE]).unwrap(); + + cargo_process(&format!("init {} --vcs git", paths::home().display())) + .with_status(101) + .with_stderr_data(str![[r#" +[CREATING] binary (application) package +[ERROR] Failed to create package `home` at `[ROOT]/home` + +Caused by: + Character at line 0 is invalid. Cargo only supports UTF-8. + +"#]]) + .run(); +} + +#[cfg(unix)] +#[cargo_test] +fn path_with_invalid_character() { + cargo_process("new --name testing test:ing") + .with_stderr_data(str![[r#" +[CREATING] binary (application) `testing` package +[WARNING] the path `[ROOT]/test:ing` contains invalid PATH characters (usually `:`, `;`, or `"`) +It is recommended to use a different name to avoid problems. +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/offline.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/offline.rs new file mode 100644 index 000000000..20c12a4b3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/offline.rs @@ -0,0 +1,788 @@ +//! Tests for --offline flag. + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::{ + basic_manifest, git, main_file, project, + registry::{Package, RegistryBuilder}, + str, Execs, +}; + +#[cargo_test] +fn offline_unused_target_dep() { + // --offline with a target dependency that is not used and not downloaded. + Package::new("unused_dep", "1.0.0").publish(); + Package::new("used_dep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + used_dep = "1.0" + [target.'cfg(unused)'.dependencies] + unused_dep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + // Do a build that downloads only what is necessary. + p.cargo("check") + .with_stderr_data(str![[r#" +... +[DOWNLOADED] used_dep v1.0.0 (registry `dummy-registry`) +... +"#]]) + .with_stderr_does_not_contain("[DOWNLOADED] unused_dep [..]") + .run(); + p.cargo("clean").run(); + // Build offline, make sure it works. + p.cargo("check --offline").run(); +} + +#[cargo_test] +fn offline_missing_optional() { + Package::new("opt_dep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + opt_dep = { version = "1.0", optional = true } + "#, + ) + .file("src/lib.rs", "") + .build(); + // Do a build that downloads only what is necessary. + p.cargo("check") + .with_stderr_does_not_contain("[DOWNLOADED] opt_dep [..]") + .run(); + p.cargo("clean").run(); + // Build offline, make sure it works. + p.cargo("check --offline").run(); + p.cargo("check --offline --features=opt_dep") + .with_stderr_data(str![[r#" +[ERROR] failed to download `opt_dep v1.0.0` + +Caused by: + attempting to make an HTTP request, but --offline was specified + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn cargo_compile_path_with_offline() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check --offline").run(); +} + +#[cargo_test] +fn cargo_compile_with_downloaded_dependency_with_offline() { + Package::new("present_dep", "1.2.3") + .file("Cargo.toml", &basic_manifest("present_dep", "1.2.3")) + .file("src/lib.rs", "") + .publish(); + + // make package downloaded + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + present_dep = "1.2.3" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check").run(); + + let p2 = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + present_dep = "1.2.3" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p2.cargo("check --offline") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] present_dep v1.2.3 +[CHECKING] bar v0.1.0 ([ROOT]/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_offline_not_try_update() { + // When --offline needs to download the registry, provide a reasonable + // error hint to run without --offline. + let p = project() + .at("bar") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + not_cached_dep = "1.2.5" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check --offline") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no matching package named `not_cached_dep` found +location searched: crates.io index +required by package `bar v0.1.0 ([ROOT]/bar)` +As a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without the offline flag. + +"#]]) + .run(); + + // While we're here, also check the config works. + p.change_file(".cargo/config.toml", "net.offline = true"); + p.cargo("check").with_status(101).with_stderr_data(str![[r#" +[ERROR] no matching package named `not_cached_dep` found +location searched: crates.io index +required by package `bar v0.1.0 ([ROOT]/bar)` +As a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without the offline flag. + +"#]]).run(); +} + +#[cargo_test] +fn compile_offline_without_maxvers_cached() { + Package::new("present_dep", "1.2.1").publish(); + Package::new("present_dep", "1.2.2").publish(); + + Package::new("present_dep", "1.2.3") + .file("Cargo.toml", &basic_manifest("present_dep", "1.2.3")) + .file( + "src/lib.rs", + r#"pub fn get_version()->&'static str {"1.2.3"}"#, + ) + .publish(); + + Package::new("present_dep", "1.2.5") + .file("Cargo.toml", &basic_manifest("present_dep", "1.2.5")) + .file("src/lib.rs", r#"pub fn get_version(){"1.2.5"}"#) + .publish(); + + // make package cached + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + present_dep = "=1.2.3" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build").run(); + + let p2 = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + present_dep = "1.2" + "#, + ) + .file( + "src/main.rs", + "\ +extern crate present_dep; +fn main(){ + println!(\"{}\", present_dep::get_version()); +}", + ) + .build(); + + p2.cargo("run --offline") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] present_dep v1.2.3 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +1.2.3 + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_forbird_git_httpsrepo_offline() { + let p = project() + .file( + "Cargo.toml", + r#" + + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["chabapok@example.com"] + + [dependencies.dep1] + git = 'https://github.com/some_user/dep1.git' + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("check --offline").with_status(101).with_stderr_data(str![[r#" +[ERROR] failed to get `dep1` as a dependency of package `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `dep1` + +Caused by: + Unable to update https://github.com/some_user/dep1.git + +Caused by: + can't checkout from 'https://github.com/some_user/dep1.git': you are in the offline mode (--offline) + +"#]]).run(); +} + +#[cargo_test] +fn compile_offline_while_transitive_dep_not_cached() { + let baz = Package::new("baz", "1.0.0"); + let baz_path = baz.archive_dst(); + baz.publish(); + + let baz_content = fs::read(&baz_path).unwrap(); + // Truncate the file to simulate a download failure. + fs::write(&baz_path, &[]).unwrap(); + + Package::new("bar", "0.1.0").dep("baz", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + // simulate download bar, but fail to download baz + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +... +Caused by: + failed to verify the checksum of `baz v1.0.0 (registry `dummy-registry`)` + +"#]]) + .run(); + + // Restore the file contents. + fs::write(&baz_path, &baz_content).unwrap(); + + p.cargo("check --offline") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to download `bar v0.1.0` + +Caused by: + attempting to make an HTTP request, but --offline was specified + +"#]]) + .run(); +} + +fn update_offline_not_cached() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("update --offline") + .with_status(101) + .with_stderr_data(str![[" +[ERROR] no matching package named `bar` found +location searched: [..] +required by package `foo v0.0.1 ([ROOT]/foo)` +As a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without the offline flag. + +"]]) + .run(); +} + +#[cargo_test] +fn update_offline_not_cached_sparse() { + let _registry = RegistryBuilder::new().http_index().build(); + update_offline_not_cached() +} + +#[cargo_test] +fn update_offline_not_cached_git() { + update_offline_not_cached() +} + +#[cargo_test] +fn cargo_compile_offline_with_cached_git_dep() { + compile_offline_with_cached_git_dep(false) +} + +#[cargo_test] +fn gitoxide_cargo_compile_offline_with_cached_git_dep_shallow_dep() { + compile_offline_with_cached_git_dep(true) +} + +fn compile_offline_with_cached_git_dep(shallow: bool) { + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "0.5.0")) + .file( + "src/lib.rs", + r#" + pub static COOL_STR:&str = "cached git repo rev1"; + "#, + ) + }); + + let repo = git2::Repository::open(&git_project.root()).unwrap(); + let rev1 = repo.revparse_single("HEAD").unwrap().id(); + + // Commit the changes and make sure we trigger a recompile + git_project.change_file( + "src/lib.rs", + r#"pub static COOL_STR:&str = "cached git repo rev2";"#, + ); + git::add(&repo); + let rev2 = git::commit(&repo); + + // cache to registry rev1 and rev2 + let prj = project() + .at("cache_git_dep") + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "cache_git_dep" + version = "0.5.0" + edition = "2015" + + [dependencies.dep1] + git = '{}' + rev = "{}" + "#, + git_project.url(), + rev1 + ), + ) + .file("src/main.rs", "fn main(){}") + .build(); + let maybe_use_shallow = |mut cargo: Execs| -> Execs { + if shallow { + cargo + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-deps") + .masquerade_as_nightly_cargo(&[ + "unstable features must be available for -Z gitoxide and -Z git", + ]); + } + cargo + }; + maybe_use_shallow(prj.cargo("build")).run(); + + prj.change_file( + "Cargo.toml", + &format!( + r#" + [package] + name = "cache_git_dep" + version = "0.5.0" + edition = "2015" + + [dependencies.dep1] + git = '{}' + rev = "{}" + "#, + git_project.url(), + rev2 + ), + ); + maybe_use_shallow(prj.cargo("build")).run(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep1] + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + &main_file(r#""hello from {}", dep1::COOL_STR"#, &["dep1"]), + ) + .build(); + + let mut cargo = p.cargo("build --offline"); + cargo.with_stderr_data(format!( + "\ +[LOCKING] 1 package to latest compatible version +[COMPILING] dep1 v0.5.0 ([ROOTURL]/dep1#[..]) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + )); + maybe_use_shallow(cargo).run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data("hello from cached git repo rev2\n") + .run(); + + p.change_file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep1] + git = '{}' + rev = "{}" + "#, + git_project.url(), + rev1 + ), + ); + + maybe_use_shallow(p.cargo("build --offline")).run(); + p.process(&p.bin("foo")) + .with_stdout_data("hello from cached git repo rev1\n") + .run(); +} + +#[cargo_test] +fn offline_resolve_optional_fail() { + // Example where resolve fails offline. + // + // This happens if at least 1 version of an optional dependency is + // available, but none of them satisfy the requirements. The current logic + // that handles this is `RegistryIndex::query_inner`, and it doesn't know + // if the package being queried is an optional one. This is not ideal, it + // would be best if it just ignored optional (unselected) dependencies. + Package::new("dep", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = { version = "1.0", optional = true } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch").run(); + + // Change dep to 2.0. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = { version = "2.0", optional = true } + "#, + ); + + p.cargo("check --offline") + .with_status(101) + .with_stderr_data( + str![[r#" +[ERROR] failed to select a version for the requirement `dep = "^2.0"` +candidate versions found which didn't match: 1.0.0 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` +perhaps a crate was updated and forgotten to be re-vendored? +As a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without the offline flag. + +"#]] + ) + .run(); +} + +#[cargo_test] +fn offline_with_all_patched() { + // Offline works if everything is patched. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = "1.0" + + [patch.crates-io] + dep = {path = "dep"} + "#, + ) + .file("src/lib.rs", "pub fn f() { dep::foo(); }") + .file("dep/Cargo.toml", &basic_manifest("dep", "1.0.0")) + .file("dep/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("check --offline").run(); +} + +#[cargo_test] +fn update_offline_cached() { + // Cache a few versions to update against + let p = project().file("src/lib.rs", "").build(); + let versions = ["1.2.3", "1.2.5", "1.2.9"]; + for vers in versions.iter() { + Package::new("present_dep", vers) + .file("Cargo.toml", &basic_manifest("present_dep", vers)) + .file( + "src/lib.rs", + format!(r#"pub fn get_version()->&'static str {{ "{}" }}"#, vers).as_str(), + ) + .publish(); + // make package cached + p.change_file( + "Cargo.toml", + format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + present_dep = "={}" + "#, + vers + ) + .as_str(), + ); + p.cargo("build").run(); + } + + let p2 = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + present_dep = "1.2" + "#, + ) + .file( + "src/main.rs", + "\ +extern crate present_dep; +fn main(){ + println!(\"{}\", present_dep::get_version()); +}", + ) + .build(); + + p2.cargo("build --offline") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] present_dep v1.2.9 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p2.rename_run("foo", "with_1_2_9") + .with_stdout_data(str![[r#" +1.2.9 + +"#]]) + .run(); + // updates happen without updating the index + p2.cargo("update present_dep --precise 1.2.3 --offline") + .with_status(0) + .with_stderr_data(str![[r#" +[DOWNGRADING] present_dep v1.2.9 -> v1.2.3 + +"#]]) + .run(); + + p2.cargo("build --offline") + .with_stderr_data(str![[r#" +[COMPILING] present_dep v1.2.3 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p2.rename_run("foo", "with_1_2_3") + .with_stdout_data(str![[r#" +1.2.3 + +"#]]) + .run(); + + // Offline update should only print package details and not index updating + p2.cargo("update --offline") + .with_status(0) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[UPDATING] present_dep v1.2.3 -> v1.2.9 + +"#]]) + .run(); + + // No v1.2.8 loaded into the cache so expect failure. + p2.cargo("update present_dep --precise 1.2.8 --offline") + .with_status(101) + .with_stderr_data( + str![[r#" +[ERROR] no matching package named `present_dep` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` +As a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without the offline flag. + +"#]] + ) + .run(); +} + +#[cargo_test] +fn offline_and_frozen_and_no_lock() { + let p = project().file("src/lib.rs", "").build(); + p.cargo("check --frozen --offline") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the lock file [ROOT]/foo/Cargo.lock needs to be updated but --frozen was passed to prevent this +If you want to try to generate the lock file without accessing the network, remove the --frozen flag and use --offline instead. + +"#]]) + .run(); +} + +#[cargo_test] +fn offline_and_locked_and_no_frozen() { + let p = project().file("src/lib.rs", "").build(); + p.cargo("check --locked --offline") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the lock file [ROOT]/foo/Cargo.lock needs to be updated but --locked was passed to prevent this +If you want to try to generate the lock file without accessing the network, remove the --locked flag and use --offline instead. + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/old_cargos.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/old_cargos.rs new file mode 100644 index 000000000..d0d5d9cb3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/old_cargos.rs @@ -0,0 +1,741 @@ +//! Tests for checking behavior of old cargos. +//! +//! These tests are ignored because it is intended to be run on a developer +//! system with a bunch of toolchains installed. This requires `rustup` to be +//! installed. It will iterate over installed toolchains, and run some tests +//! over each one, producing a report at the end. As of this writing, I have +//! tested 1.0 to 1.51. Run this with: +//! +//! ```console +//! cargo test --test testsuite -- old_cargos --nocapture --ignored +//! ``` + +use std::fs; + +use cargo::CargoResult; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Dependency, Package}; +use cargo_test_support::{cargo_exe, execs, paths, process, project, rustc_host, str}; +use cargo_util::{ProcessBuilder, ProcessError}; +use semver::Version; + +fn tc_process(cmd: &str, toolchain: &str) -> ProcessBuilder { + let mut p = if toolchain == "this" { + if cmd == "cargo" { + process(&cargo_exe()) + } else { + process(cmd) + } + } else { + let mut cmd = process(cmd); + cmd.arg(format!("+{}", toolchain)); + cmd + }; + // Reset PATH since `process` modifies it to remove rustup. + p.env("PATH", std::env::var_os("PATH").unwrap()); + p +} + +/// Returns a sorted list of all toolchains. +/// +/// The returned value includes the parsed version, and the rustup toolchain +/// name as a string. +fn collect_all_toolchains() -> Vec<(Version, String)> { + let rustc_version = |tc| { + let mut cmd = tc_process("rustc", tc); + cmd.arg("-V"); + let output = cmd.exec_with_output().expect("rustc installed"); + let version = std::str::from_utf8(&output.stdout).unwrap(); + let parts: Vec<_> = version.split_whitespace().collect(); + assert_eq!(parts[0], "rustc"); + assert!(parts[1].starts_with("1.")); + Version::parse(parts[1]).expect("valid version") + }; + + // Provide a way to override the list. + if let Ok(tcs) = std::env::var("OLD_CARGO") { + return tcs + .split(',') + .map(|tc| (rustc_version(tc), tc.to_string())) + .collect(); + } + + let host = rustc_host(); + // I tend to have lots of toolchains installed, but I don't want to test + // all of them (like dated nightlies, or toolchains for non-host targets). + let valid_names = &[ + format!("stable-{}", host), + format!("beta-{}", host), + format!("nightly-{}", host), + ]; + + let output = ProcessBuilder::new("rustup") + .args(&["toolchain", "list"]) + .exec_with_output() + .expect("rustup should be installed"); + let stdout = std::str::from_utf8(&output.stdout).unwrap(); + let mut toolchains: Vec<_> = stdout + .lines() + .map(|line| { + // Some lines say things like (default), just get the version. + line.split_whitespace().next().expect("non-empty line") + }) + .filter(|line| { + line.ends_with(&host) + && (line.starts_with("1.") || valid_names.iter().any(|name| name == line)) + }) + .map(|line| (rustc_version(line), line.to_string())) + .collect(); + + toolchains.sort_by(|a, b| a.0.cmp(&b.0)); + toolchains +} + +/// Returns whether the default toolchain is the stable version. +fn default_toolchain_is_stable() -> bool { + let default = tc_process("rustc", "this").arg("-V").exec_with_output(); + let stable = tc_process("rustc", "stable").arg("-V").exec_with_output(); + match (default, stable) { + (Ok(d), Ok(s)) => d.stdout == s.stdout, + _ => false, + } +} + +// This is a test for exercising the behavior of older versions of cargo with +// the new feature syntax. +// +// The test involves a few dependencies with different feature requirements: +// +// * `bar` 1.0.0 is the base version that does not use the new syntax. +// * `bar` 1.0.1 has a feature with the new syntax, but the feature is unused. +// The optional dependency `new-baz-dep` should not be activated. +// * `bar` 1.0.2 has a dependency on `baz` that *requires* the new feature +// syntax. +#[ignore = "must be run manually, requires old cargo installations"] +#[cargo_test] +fn new_features() { + let registry = registry::init(); + if std::process::Command::new("rustup").output().is_err() { + panic!("old_cargos requires rustup to be installed"); + } + Package::new("new-baz-dep", "1.0.0").publish(); + + Package::new("baz", "1.0.0").publish(); + let baz101_cksum = Package::new("baz", "1.0.1") + .add_dep(Dependency::new("new-baz-dep", "1.0").optional(true)) + .feature("new-feat", &["dep:new-baz-dep"]) + .publish(); + + let bar100_cksum = Package::new("bar", "1.0.0") + .add_dep(Dependency::new("baz", "1.0").optional(true)) + .feature("feat", &["baz"]) + .publish(); + let bar101_cksum = Package::new("bar", "1.0.1") + .add_dep(Dependency::new("baz", "1.0").optional(true)) + .feature("feat", &["dep:baz"]) + .publish(); + let bar102_cksum = Package::new("bar", "1.0.2") + .add_dep(Dependency::new("baz", "1.0").enable_features(&["new-feat"])) + .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 lock_bar_to = |toolchain_version: &Version, bar_version| { + let lock = if toolchain_version < &Version::new(1, 12, 0) { + let url = registry.index_url(); + match bar_version { + 100 => format!( + r#" + [root] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar 1.0.0 (registry+{url})", + ] + + [[package]] + name = "bar" + version = "1.0.0" + source = "registry+{url}" + "#, + url = url + ), + 101 => format!( + r#" + [root] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar 1.0.1 (registry+{url})", + ] + + [[package]] + name = "bar" + version = "1.0.1" + source = "registry+{url}" + "#, + url = url + ), + 102 => format!( + r#" + [root] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar 1.0.2 (registry+{url})", + ] + + [[package]] + name = "bar" + version = "1.0.2" + source = "registry+{url}" + dependencies = [ + "baz 1.0.1 (registry+{url})", + ] + + [[package]] + name = "baz" + version = "1.0.1" + source = "registry+{url}" + "#, + url = url + ), + _ => panic!("unexpected version"), + } + } else { + match bar_version { + 100 => format!( + r#" + [root] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "bar" + version = "1.0.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + + [metadata] + "checksum bar 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "{}" + "#, + bar100_cksum + ), + 101 => format!( + r#" + [root] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "bar" + version = "1.0.1" + source = "registry+https://github.com/rust-lang/crates.io-index" + + [metadata] + "checksum bar 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "{}" + "#, + bar101_cksum + ), + 102 => format!( + r#" + [root] + name = "foo" + version = "0.1.0" + dependencies = [ + "bar 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "bar" + version = "1.0.2" + source = "registry+https://github.com/rust-lang/crates.io-index" + dependencies = [ + "baz 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "baz" + version = "1.0.1" + source = "registry+https://github.com/rust-lang/crates.io-index" + + [metadata] + "checksum bar 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "{bar102_cksum}" + "checksum baz 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "{baz101_cksum}" + "#, + bar102_cksum = bar102_cksum, + baz101_cksum = baz101_cksum + ), + _ => panic!("unexpected version"), + } + }; + p.change_file("Cargo.lock", &lock); + }; + + let toolchains = collect_all_toolchains(); + + let config_path = paths::home().join(".cargo/config"); + let lock_path = p.root().join("Cargo.lock"); + + struct ToolchainBehavior { + bar: Option, + baz: Option, + new_baz_dep: Option, + } + + // Collect errors to print at the end. One entry per toolchain, a list of + // strings to print. + let mut unexpected_results: Vec> = Vec::new(); + + for (version, toolchain) in &toolchains { + if version >= &Version::new(1, 15, 0) && version < &Version::new(1, 18, 0) { + // These versions do not stay within the sandbox, and chokes on + // Cargo's own `Cargo.toml`. + continue; + } + let mut tc_result = Vec::new(); + // Write a config appropriate for this version. + if version < &Version::new(1, 12, 0) { + fs::write( + &config_path, + format!( + r#" + [registry] + index = "{}" + "#, + registry.index_url() + ), + ) + .unwrap(); + } else { + fs::write( + &config_path, + format!( + " + [source.crates-io] + registry = 'https://wut' # only needed by 1.12 + replace-with = 'dummy-registry' + + [source.dummy-registry] + registry = '{}' + ", + registry.index_url() + ), + ) + .unwrap(); + } + + // Fetches the version of a package in the lock file. + let pkg_version = |pkg| -> Option { + let output = tc_process("cargo", toolchain) + .args(&["pkgid", pkg]) + .cwd(p.root()) + .exec_with_output() + .ok()?; + let stdout = std::str::from_utf8(&output.stdout).unwrap(); + let version = stdout + .trim() + .rsplitn(2, ['@', ':']) + .next() + .expect("version after colon"); + Some(Version::parse(version).expect("parseable version")) + }; + + // Runs `cargo build` and returns the versions selected in the lock. + let run_cargo = || -> CargoResult { + match tc_process("cargo", toolchain) + .args(&["build", "--verbose"]) + .cwd(p.root()) + .exec_with_output() + { + Ok(_output) => { + eprintln!("{} ok", toolchain); + let bar = pkg_version("bar"); + let baz = pkg_version("baz"); + let new_baz_dep = pkg_version("new-baz-dep"); + Ok(ToolchainBehavior { + bar, + baz, + new_baz_dep, + }) + } + Err(e) => { + eprintln!("{} err {}", toolchain, e); + Err(e) + } + } + }; + + macro_rules! check_lock { + ($tc_result:ident, $pkg:expr, $which:expr, $actual:expr, None) => { + check_lock!(= $tc_result, $pkg, $which, $actual, None); + }; + ($tc_result:ident, $pkg:expr, $which:expr, $actual:expr, $expected:expr) => { + check_lock!(= $tc_result, $pkg, $which, $actual, Some(Version::parse($expected).unwrap())); + }; + (= $tc_result:ident, $pkg:expr, $which:expr, $actual:expr, $expected:expr) => { + let exp: Option = $expected; + if $actual != $expected { + $tc_result.push(format!( + "{} for {} saw {:?} but expected {:?}", + $which, $pkg, $actual, exp + )); + } + }; + } + + let check_err_contains = |tc_result: &mut Vec<_>, err: anyhow::Error, contents| { + if let Some(ProcessError { + stderr: Some(stderr), + .. + }) = err.downcast_ref::() + { + let stderr = std::str::from_utf8(stderr).unwrap(); + if !stderr.contains(contents) { + tc_result.push(format!( + "{} expected to see error contents:\n{}\nbut saw:\n{}", + toolchain, contents, stderr + )); + } + } else { + panic!("{} unexpected error {}", toolchain, err); + } + }; + + // Unlocked behavior. + let which = "unlocked"; + lock_path.rm_rf(); + p.build_dir().rm_rf(); + match run_cargo() { + Ok(behavior) => { + if version < &Version::new(1, 51, 0) { + check_lock!(tc_result, "bar", which, behavior.bar, "1.0.2"); + check_lock!(tc_result, "baz", which, behavior.baz, "1.0.1"); + check_lock!(tc_result, "new-baz-dep", which, behavior.new_baz_dep, None); + } else if version >= &Version::new(1, 51, 0) && version <= &Version::new(1, 59, 0) { + check_lock!(tc_result, "bar", which, behavior.bar, "1.0.0"); + check_lock!(tc_result, "baz", which, behavior.baz, None); + check_lock!(tc_result, "new-baz-dep", which, behavior.new_baz_dep, None); + } + // Starting with 1.60, namespaced-features has been stabilized. + else { + check_lock!(tc_result, "bar", which, behavior.bar, "1.0.2"); + check_lock!(tc_result, "baz", which, behavior.baz, "1.0.1"); + check_lock!( + tc_result, + "new-baz-dep", + which, + behavior.new_baz_dep, + "1.0.0" + ); + } + } + Err(e) => { + if version < &Version::new(1, 49, 0) { + // Old versions don't like the dep: syntax. + check_err_contains( + &mut tc_result, + e, + "which is neither a dependency nor another feature", + ); + } else if version >= &Version::new(1, 49, 0) && version < &Version::new(1, 51, 0) { + check_err_contains( + &mut tc_result, + e, + "requires the `-Z namespaced-features` flag", + ); + } else { + tc_result.push(format!("unlocked build failed: {}", e)); + } + } + } + + let which = "locked bar 1.0.0"; + lock_bar_to(version, 100); + match run_cargo() { + Ok(behavior) => { + check_lock!(tc_result, "bar", which, behavior.bar, "1.0.0"); + check_lock!(tc_result, "baz", which, behavior.baz, None); + check_lock!(tc_result, "new-baz-dep", which, behavior.new_baz_dep, None); + } + Err(e) => { + tc_result.push(format!("bar 1.0.0 locked build failed: {}", e)); + } + } + + let which = "locked bar 1.0.1"; + lock_bar_to(version, 101); + match run_cargo() { + Ok(behavior) => { + check_lock!(tc_result, "bar", which, behavior.bar, "1.0.1"); + check_lock!(tc_result, "baz", which, behavior.baz, None); + check_lock!(tc_result, "new-baz-dep", which, behavior.new_baz_dep, None); + } + Err(e) => { + if version < &Version::new(1, 49, 0) { + // Old versions don't like the dep: syntax. + check_err_contains( + &mut tc_result, + e, + "which is neither a dependency nor another feature", + ); + } else if version >= &Version::new(1, 49, 0) && version < &Version::new(1, 51, 0) { + check_err_contains( + &mut tc_result, + e, + "requires the `-Z namespaced-features` flag", + ); + } else { + // When version >= 1.51 and <= 1.59, + // 1.0.1 can't be used without -Znamespaced-features + // It gets filtered out of the index. + check_err_contains( + &mut tc_result, + e, + "candidate versions found which didn't match: 1.0.2, 1.0.0", + ); + } + } + } + + let which = "locked bar 1.0.2"; + lock_bar_to(version, 102); + match run_cargo() { + Ok(behavior) => { + if version <= &Version::new(1, 59, 0) { + check_lock!(tc_result, "bar", which, behavior.bar, "1.0.2"); + check_lock!(tc_result, "baz", which, behavior.baz, "1.0.1"); + check_lock!(tc_result, "new-baz-dep", which, behavior.new_baz_dep, None); + } + // Starting with 1.60, namespaced-features has been stabilized. + else { + check_lock!(tc_result, "bar", which, behavior.bar, "1.0.2"); + check_lock!(tc_result, "baz", which, behavior.baz, "1.0.1"); + check_lock!( + tc_result, + "new-baz-dep", + which, + behavior.new_baz_dep, + "1.0.0" + ); + } + } + Err(e) => { + if version < &Version::new(1, 49, 0) { + // Old versions don't like the dep: syntax. + check_err_contains( + &mut tc_result, + e, + "which is neither a dependency nor another feature", + ); + } else if version >= &Version::new(1, 49, 0) && version < &Version::new(1, 51, 0) { + check_err_contains( + &mut tc_result, + e, + "requires the `-Z namespaced-features` flag", + ); + } else { + // When version >= 1.51 and <= 1.59, + // baz can't lock to 1.0.1, it requires -Znamespaced-features + check_err_contains( + &mut tc_result, + e, + "candidate versions found which didn't match: 1.0.0", + ); + } + } + } + + unexpected_results.push(tc_result); + } + + // Generate a report. + let mut has_err = false; + for ((tc_vers, tc_name), errs) in toolchains.iter().zip(unexpected_results) { + if errs.is_empty() { + continue; + } + eprintln!("error: toolchain {} (version {}):", tc_name, tc_vers); + for err in errs { + eprintln!(" {}", err); + } + has_err = true; + } + if has_err { + panic!("at least one toolchain did not run as expected"); + } +} + +#[cargo_test] +#[ignore = "must be run manually, requires old cargo installations"] +fn index_cache_rebuild() { + // Checks that the index cache gets rebuilt. + // + // 1.48 will not cache entries with features with the same name as a + // dependency. If the cache does not get rebuilt, then running with + // `-Znamespaced-features` would prevent the new cargo from seeing those + // entries. The index cache version was changed to prevent this from + // happening, and switching between versions should work correctly + // (although it will thrash the cash, that's better than not working + // correctly. + let registry = registry::init(); + Package::new("baz", "1.0.0").publish(); + Package::new("bar", "1.0.0").publish(); + Package::new("bar", "1.0.1") + .add_dep(Dependency::new("baz", "1.0").optional(true)) + .feature("baz", &["dep:baz"]) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [source.crates-io] + replace-with = 'dummy-registry' + + [source.dummy-registry] + registry = '{}' + "#, + registry.index_url() + ), + ) + .build(); + + // This version of Cargo errors on index entries that have overlapping + // feature names, so 1.0.1 will be missing. + execs() + .with_process_builder(tc_process("cargo", "1.48.0")) + .arg("check") + .cwd(p.root()) + .with_stderr_data(str![[r#" +[UPDATING] `[ROOT]/registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `[ROOT]/registry`) +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] dev [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + fs::remove_file(p.root().join("Cargo.lock")).unwrap(); + + // This should rebuild the cache and use 1.0.1. + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] no edition set: defaulting to the 2015 edition while the latest is [..] +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.1 (registry `dummy-registry`) +[CHECKING] bar v1.0.1 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + fs::remove_file(p.root().join("Cargo.lock")).unwrap(); + + // Verify 1.48 can still resolve, and is at 1.0.0. + execs() + .with_process_builder(tc_process("cargo", "1.48.0")) + .arg("tree") + .cwd(p.root()) + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +#[ignore = "must be run manually, requires old cargo installations"] +fn avoids_split_debuginfo_collision() { + // Test needs two different toolchains. + // If the default toolchain is stable, then it won't work. + if default_toolchain_is_stable() { + return; + } + // Checks for a bug where .o files were being incorrectly shared between + // different toolchains using incremental and split-debuginfo on macOS. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [profile.dev] + split-debuginfo = "unpacked" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + execs() + .with_process_builder(tc_process("cargo", "stable")) + .arg("build") + .env("CARGO_INCREMENTAL", "1") + .cwd(p.root()) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build") + .env("CARGO_INCREMENTAL", "1") + .with_stderr_data(str![[r#" +[WARNING] no edition set: defaulting to the 2015 edition while the latest is [..] +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + execs() + .with_process_builder(tc_process("cargo", "stable")) + .arg("build") + .env("CARGO_INCREMENTAL", "1") + .cwd(p.root()) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/open_namespaces.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/open_namespaces.rs new file mode 100644 index 000000000..c7506dfae --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/open_namespaces.rs @@ -0,0 +1,460 @@ +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn within_namespace_requires_feature() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("read-manifest") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `open-namespaces` is required + + The package requires the Cargo feature called `open-namespaces`, but that feature is not stabilized in this version of Cargo ([..]). + Consider adding `cargo-features = ["open-namespaces"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#open-namespaces for more information about the status of this feature. + +"#]]) + .run(); +} + +#[cargo_test] +fn implicit_lib_within_namespace() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["open-namespaces"] + + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("read-manifest") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .with_stdout_data( + str![[r#" +{ + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#foo::bar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo::bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo::bar", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" +} +"#]] + .is_json(), + ) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn implicit_bin_within_namespace() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["open-namespaces"] + + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("read-manifest") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .with_stdout_data( + str![[r#" +{ + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#foo::bar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo::bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo::bar", + "src_path": "[ROOT]/foo/src/main.rs", + "test": true + } + ], + "version": "0.0.1" +} +"#]] + .is_json(), + ) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn explicit_bin_within_namespace() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["open-namespaces"] + + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + + [[bin]] + name = "foo-bar" + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/foo-bar/main.rs", "fn main() {}") + .build(); + + p.cargo("read-manifest") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .with_stdout_data( + str![[r#" +{ + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#foo::bar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo::bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo::bar", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + }, + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2015", + "kind": [ + "bin" + ], + "name": "foo-bar", + "src_path": "[ROOT]/foo/src/bin/foo-bar/main.rs", + "test": true + } + ], + "version": "0.0.1" +} +"#]] + .is_json(), + ) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +#[cfg(unix)] +fn namespaced_script_name() { + let p = cargo_test_support::project() + .file( + "foo::bar.rs", + r#"--- +cargo-features = ["open-namespaces"] +package.edition = "2021" +--- + +fn main() {} +"#, + ) + .build(); + + p.cargo("read-manifest -Zscript --manifest-path foo::bar.rs") + .masquerade_as_nightly_cargo(&["script", "open-namespaces"]) + .with_stdout_data( + str![[r#" +{ + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2021", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/foo::bar.rs#foo::bar@0.0.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/foo::bar.rs", + "metadata": null, + "name": "foo::bar", + "publish": [], + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2021", + "kind": [ + "bin" + ], + "name": "foo::bar", + "src_path": "[ROOT]/home/.cargo/target/[HASH]/foo::bar.rs", + "test": true + } + ], + "version": "0.0.0" +} +"#]] + .is_json(), + ) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn generate_pkgid_with_namespace() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["open-namespaces"] + + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .run(); + p.cargo("pkgid") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .with_stdout_data(str![[r#" +path+[ROOTURL]/foo#foo::bar@0.0.1 + +"#]]) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn update_spec_accepts_namespaced_name() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["open-namespaces"] + + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .run(); + p.cargo("update foo::bar") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .with_stdout_data(str![""]) + .with_stderr_data(str![[r#" +[LOCKING] 0 packages to latest compatible versions + +"#]]) + .run(); +} + +#[cargo_test] +fn update_spec_accepts_namespaced_pkgid() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["open-namespaces"] + + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .run(); + p.cargo(&format!("update path+{}#foo::bar@0.0.1", p.url())) + .masquerade_as_nightly_cargo(&["open-namespaces"]) + .with_stdout_data(str![""]) + .with_stderr_data(str![[r#" +[LOCKING] 0 packages to latest compatible versions + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(unix)] // until we get proper packaging support +fn publish_namespaced() { + use cargo_test_support::registry::RegistryBuilder; + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["open-namespaces"] + + [package] + name = "foo::bar" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .masquerade_as_nightly_cargo(&["script", "open-namespaces"]) + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo::bar v0.0.1 ([ROOT]/foo) +[ERROR] failed to prepare local package for uploading + +Caused by: + cannot publish with `open-namespaces` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/owner.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/owner.rs new file mode 100644 index 000000000..ec473183f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/owner.rs @@ -0,0 +1,194 @@ +//! Tests for the `cargo owner` command. + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::{self, api_path}; +use cargo_test_support::str; + +fn setup(name: &str, content: Option<&str>) { + let dir = api_path().join(format!("api/v1/crates/{}", name)); + dir.mkdir_p(); + if let Some(body) = content { + fs::write(dir.join("owners"), body).unwrap(); + } +} + +#[cargo_test] +fn simple_list() { + let registry = registry::init(); + let content = r#"{ + "users": [ + { + "id": 70, + "login": "github:rust-lang:core", + "name": "Core" + }, + { + "id": 123, + "login": "octocat" + } + ] + }"#; + setup("foo", Some(content)); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("owner -l") + .replace_crates_io(registry.index_url()) + .with_stdout_data(str![[r#" +github:rust-lang:core (Core) +octocat + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_add() { + let registry = registry::init(); + setup("foo", None); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("owner -a username") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] failed to invite owners to crate `foo` on registry at [ROOTURL]/api + +Caused by: + EOF while parsing a value at line 1 column 0 + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_add_with_asymmetric() { + let registry = registry::RegistryBuilder::new() + .http_api() + .token(cargo_test_support::registry::Token::rfc_key()) + .build(); + setup("foo", None); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // 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("-Zasymmetric-token") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .replace_crates_io(registry.index_url()) + .with_status(0) + .run(); +} + +#[cargo_test] +fn simple_remove() { + let registry = registry::init(); + setup("foo", None); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("owner -r username") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[OWNER] removing ["username"] from crate foo +[ERROR] failed to remove owners from crate `foo` on registry at [ROOTURL]/api + +Caused by: + EOF while parsing a value at line 1 column 0 + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_remove_with_asymmetric() { + let registry = registry::RegistryBuilder::new() + .http_api() + .token(cargo_test_support::registry::Token::rfc_key()) + .build(); + setup("foo", None); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // 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("-Zasymmetric-token") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .with_status(0) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package.rs new file mode 100644 index 000000000..ae4de6e29 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package.rs @@ -0,0 +1,7192 @@ +//! Tests for the `cargo package` command. + +use std::fs::{self, read_to_string, File}; +use std::path::Path; + +use cargo_test_support::prelude::*; +use cargo_test_support::publish::validate_crate_contents; +use cargo_test_support::registry::{self, Package}; +use cargo_test_support::{ + basic_manifest, cargo_process, git, paths, project, rustc_host, str, symlink_supported, t, + Project, ProjectBuilder, +}; +use flate2::read::GzDecoder; +use tar::Archive; + +#[cargo_test] +fn simple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file("src/bar.txt", "") // should be ignored when packaging + .build(); + + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + "Cargo.lock", + ], + (), + ); +} + +#[cargo_test] +fn metadata_warning() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + repository = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn package_verbose() { + let root = paths::root().join("all"); + let repo = git::repo(&root) + .file("Cargo.toml", &basic_manifest("foo", "0.0.1")) + .file("src/main.rs", "fn main() {}") + .file("a/a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/a/src/lib.rs", "") + .build(); + cargo_process("build").cwd(repo.root()).run(); + + println!("package main repo"); + cargo_process("package -v --no-verify") + .cwd(repo.root()) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/all) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] src/main.rs +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); + + let f = File::open(&repo.root().join("target/package/foo-0.0.1.crate")).unwrap(); + let vcs_contents = format!( + r#"{{ + "git": {{ + "sha1": "{}" + }}, + "path_in_vcs": "" +}}"#, + repo.revparse_head() + ); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + ".cargo_vcs_info.json", + ], + [(".cargo_vcs_info.json", &vcs_contents)], + ); + + println!("package sub-repo"); + cargo_process("package -v --no-verify") + .cwd(repo.root().join("a/a")) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] a v0.0.1 ([ROOT]/all/a/a) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] src/lib.rs +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); + + let f = File::open(&repo.root().join("a/a/target/package/a-0.0.1.crate")).unwrap(); + let vcs_contents = format!( + r#"{{ + "git": {{ + "sha1": "{}" + }}, + "path_in_vcs": "a/a" +}}"#, + repo.revparse_head() + ); + validate_crate_contents( + f, + "a-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + ".cargo_vcs_info.json", + ], + [(".cargo_vcs_info.json", &vcs_contents)], + ); +} + +#[cargo_test] +fn package_verification() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("build").run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn vcs_file_collision() { + let p = project().build(); + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + documentation = "foo" + homepage = "foo" + repository = "foo" + exclude = ["*.no-existe"] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() {} + "#, + ) + .file(".cargo_vcs_info.json", "foo") + .build(); + p.cargo("package") + .arg("--no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid inclusion of reserved file name .cargo_vcs_info.json in package source + +"#]]) + .run(); +} + +#[cargo_test] +fn orig_file_collision() { + let p = project().build(); + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + documentation = "foo" + homepage = "foo" + repository = "foo" + exclude = ["*.no-existe"] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() {} + "#, + ) + .file("Cargo.toml.orig", "oops") + .build(); + p.cargo("package") + .arg("--no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid inclusion of reserved file name Cargo.toml.orig in package source + +"#]]) + .run(); +} + +#[cargo_test] +fn path_dependency_no_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] all dependencies must have a version specified when packaging. +dependency `bar` does not specify a version +Note: The packaged dependency will use the version from crates.io, +the `path` specification will be removed from the dependency declaration. + +"#]]) + .run(); +} + +#[cargo_test] +fn git_dependency_no_version() { + registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies.foo] + git = "git://path/to/nowhere" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] all dependencies must have a version specified when packaging. +dependency `foo` does not specify a version +Note: The packaged dependency will use the version from crates.io, +the `git` specification will be removed from the dependency declaration. + +"#]]) + .run(); +} + +#[cargo_test] +fn exclude() { + let root = paths::root().join("exclude"); + let repo = git::repo(&root) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = [ + "*.txt", + # file in root + "file_root_1", # NO_CHANGE (ignored) + "/file_root_2", # CHANGING (packaged -> ignored) + "file_root_3/", # NO_CHANGE (packaged) + "file_root_4/*", # NO_CHANGE (packaged) + "file_root_5/**", # NO_CHANGE (packaged) + # file in sub-dir + "file_deep_1", # CHANGING (packaged -> ignored) + "/file_deep_2", # NO_CHANGE (packaged) + "file_deep_3/", # NO_CHANGE (packaged) + "file_deep_4/*", # NO_CHANGE (packaged) + "file_deep_5/**", # NO_CHANGE (packaged) + # dir in root + "dir_root_1", # CHANGING (packaged -> ignored) + "/dir_root_2", # CHANGING (packaged -> ignored) + "dir_root_3/", # CHANGING (packaged -> ignored) + "dir_root_4/*", # NO_CHANGE (ignored) + "dir_root_5/**", # NO_CHANGE (ignored) + # dir in sub-dir + "dir_deep_1", # CHANGING (packaged -> ignored) + "/dir_deep_2", # NO_CHANGE + "dir_deep_3/", # CHANGING (packaged -> ignored) + "dir_deep_4/*", # CHANGING (packaged -> ignored) + "dir_deep_5/**", # CHANGING (packaged -> ignored) + ] + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file("bar.txt", "") + .file("src/bar.txt", "") + // File in root. + .file("file_root_1", "") + .file("file_root_2", "") + .file("file_root_3", "") + .file("file_root_4", "") + .file("file_root_5", "") + // File in sub-dir. + .file("some_dir/file_deep_1", "") + .file("some_dir/file_deep_2", "") + .file("some_dir/file_deep_3", "") + .file("some_dir/file_deep_4", "") + .file("some_dir/file_deep_5", "") + // Dir in root. + .file("dir_root_1/some_dir/file", "") + .file("dir_root_2/some_dir/file", "") + .file("dir_root_3/some_dir/file", "") + .file("dir_root_4/some_dir/file", "") + .file("dir_root_5/some_dir/file", "") + // Dir in sub-dir. + .file("some_dir/dir_deep_1/some_dir/file", "") + .file("some_dir/dir_deep_2/some_dir/file", "") + .file("some_dir/dir_deep_3/some_dir/file", "") + .file("some_dir/dir_deep_4/some_dir/file", "") + .file("some_dir/dir_deep_5/some_dir/file", "") + .build(); + + cargo_process("package --no-verify -v") + .cwd(repo.root()) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/exclude) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] file_root_3 +[ARCHIVING] file_root_4 +[ARCHIVING] file_root_5 +[ARCHIVING] some_dir/dir_deep_2/some_dir/file +[ARCHIVING] some_dir/dir_deep_4/some_dir/file +[ARCHIVING] some_dir/dir_deep_5/some_dir/file +[ARCHIVING] some_dir/file_deep_2 +[ARCHIVING] some_dir/file_deep_3 +[ARCHIVING] some_dir/file_deep_4 +[ARCHIVING] some_dir/file_deep_5 +[ARCHIVING] src/main.rs +[PACKAGED] 15 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); + + assert!(repo.root().join("target/package/foo-0.0.1.crate").is_file()); + + cargo_process("package -l") + .cwd(repo.root()) + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +file_root_3 +file_root_4 +file_root_5 +some_dir/dir_deep_2/some_dir/file +some_dir/dir_deep_4/some_dir/file +some_dir/dir_deep_5/some_dir/file +some_dir/file_deep_2 +some_dir/file_deep_3 +some_dir/file_deep_4 +some_dir/file_deep_5 +src/main.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn include() { + let root = paths::root().join("include"); + let repo = git::repo(&root) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + include = ["foo.txt", "**/*.rs", "Cargo.toml", ".dotfile"] + "#, + ) + .file("foo.txt", "") + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file(".dotfile", "") + // Should be ignored when packaging. + .file("src/bar.txt", "") + .build(); + + cargo_process("package --no-verify -v") + .cwd(repo.root()) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[WARNING] both package.include and package.exclude are specified; the exclude list will be ignored +[PACKAGING] foo v0.0.1 ([ROOT]/include) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] .dotfile +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] foo.txt +[ARCHIVING] src/main.rs +[PACKAGED] 7 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); +} + +#[cargo_test] +fn package_lib_with_bin() { + let p = project() + .file("src/main.rs", "extern crate foo; fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("package -v").run(); +} + +#[cargo_test] +fn package_git_submodule() { + let project = git::new("foo", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = ["foo@example.com"] + license = "MIT" + description = "foo" + repository = "foo" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + }); + let library = git::new("bar", |library| { + library.no_manifest().file("Makefile", "all:") + }); + + let repository = git2::Repository::open(&project.root()).unwrap(); + let url = library.root().to_url().to_string(); + git::add_submodule(&repository, &url, Path::new("bar")); + git::commit(&repository); + + let repository = git2::Repository::open(&project.root().join("bar")).unwrap(); + repository + .reset( + &repository.revparse_single("HEAD").unwrap(), + git2::ResetType::Hard, + None, + ) + .unwrap(); + + project + .cargo("package --no-verify -v") + .with_stderr_data(str![[r#" +... +[ARCHIVING] bar/Makefile +... +"#]]) + .run(); +} + +#[cargo_test] +/// Tests if a symlink to a git submodule is properly handled. +/// +/// This test requires you to be able to make symlinks. +/// For windows, this may require you to enable developer mode. +fn package_symlink_to_submodule() { + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(windows)] + use std::os::windows::fs::symlink_dir as symlink; + + if !symlink_supported() { + return; + } + + let project = git::new("foo", |project| { + project.file("src/lib.rs", "pub fn foo() {}") + }); + + let library = git::new("submodule", |library| { + library.no_manifest().file("Makefile", "all:") + }); + + let repository = git2::Repository::open(&project.root()).unwrap(); + let url = library.root().to_url().to_string(); + git::add_submodule(&repository, &url, Path::new("submodule")); + t!(symlink( + &project.root().join("submodule"), + &project.root().join("submodule-link") + )); + git::add(&repository); + git::commit(&repository); + + let repository = git2::Repository::open(&project.root().join("submodule")).unwrap(); + repository + .reset( + &repository.revparse_single("HEAD").unwrap(), + git2::ResetType::Hard, + None, + ) + .unwrap(); + + project + .cargo("package --no-verify -v") + .with_stderr_contains("[ARCHIVING] submodule/Makefile") + .with_stderr_does_not_contain("[ARCHIVING] submodule-link/.git/config") + .run(); +} + +#[cargo_test] +fn no_duplicates_from_modified_tracked_files() { + let p = git::new("all", |p| p.file("src/main.rs", "fn main() {}")); + p.change_file("src/main.rs", r#"fn main() { println!("A change!"); }"#); + p.cargo("build").run(); + p.cargo("package --list --allow-dirty") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn ignore_nested() { + let cargo_toml = r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + homepage = "https://example.com/" + "#; + let main_rs = r#" + fn main() { println!("hello"); } + "#; + let p = project() + .file("Cargo.toml", cargo_toml) + .file("src/main.rs", main_rs) + // If a project happens to contain a copy of itself, we should + // ignore it. + .file("a_dir/foo/Cargo.toml", cargo_toml) + .file("a_dir/foo/src/main.rs", main_rs) + .build(); + + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + (), + ); +} + +// Windows doesn't allow these characters in filenames. +#[cfg(unix)] +#[cargo_test] +fn package_weird_characters() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file("src/:foo", "") + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] cannot package a filename with a special character `:`: src/:foo + +"#]]) + .run(); +} + +#[cargo_test] +fn repackage_on_source_change() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("package").run(); + + // Add another source file + p.change_file("src/foo.rs", r#"fn main() { println!("foo"); }"#); + + // Check that cargo rebuilds the tarball + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Check that the tarball contains the added file + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + "src/foo.rs", + ], + (), + ); +} + +#[cargo_test] +/// Tests if a broken symlink is properly handled when packaging. +/// +/// This test requires you to be able to make symlinks. +/// For windows, this may require you to enable developer mode. +fn broken_symlink() { + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(windows)] + use std::os::windows::fs::symlink_dir as symlink; + + if !symlink_supported() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = 'foo' + documentation = 'foo' + homepage = 'foo' + repository = 'foo' + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + t!(symlink("nowhere", &p.root().join("src/foo.rs"))); + + p.cargo("package -v") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] failed to prepare local package for uploading + +Caused by: + failed to open for archiving: `[ROOT]/foo/src/foo.rs` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +/// Tests if a broken but excluded symlink is ignored. +/// See issue rust-lang/cargo#10917 +/// +/// This test requires you to be able to make symlinks. +/// For windows, this may require you to enable developer mode. +fn broken_but_excluded_symlink() { + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(windows)] + use std::os::windows::fs::symlink_dir as symlink; + + if !symlink_supported() { + return; + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = 'foo' + documentation = 'foo' + homepage = 'foo' + repository = 'foo' + exclude = ["src/foo.rs"] + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + t!(symlink("nowhere", &p.root().join("src/foo.rs"))); + + p.cargo("package -v --list") + // `src/foo.rs` is excluded. + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(not(windows))] // https://github.com/libgit2/libgit2/issues/6250 +/// Test that /dir and /dir/ matches symlinks to directories. +fn gitignore_symlink_dir() { + if !symlink_supported() { + return; + } + + let (p, _repo) = git::new_repo("foo", |p| { + p.file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .symlink_dir("src", "src1") + .symlink_dir("src", "src2") + .symlink_dir("src", "src3") + .symlink_dir("src", "src4") + .file(".gitignore", "/src1\n/src2/\nsrc3\nsrc4/") + }); + + p.cargo("package -l --no-metadata") + .with_stderr_data("") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +.gitignore +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(not(windows))] // https://github.com/libgit2/libgit2/issues/6250 +/// Test that /dir and /dir/ matches symlinks to directories in dirty working directory. +fn gitignore_symlink_dir_dirty() { + if !symlink_supported() { + return; + } + + let (p, _repo) = git::new_repo("foo", |p| { + p.file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file(".gitignore", "/src1\n/src2/\nsrc3\nsrc4/") + }); + + p.symlink("src", "src1"); + p.symlink("src", "src2"); + p.symlink("src", "src3"); + p.symlink("src", "src4"); + + p.cargo("package -l --no-metadata") + .with_stderr_data("") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +.gitignore +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + + p.cargo("package -l --no-metadata --allow-dirty") + .with_stderr_data("") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +.gitignore +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); +} + +#[cargo_test] +/// Tests if a symlink to a directory is properly included. +/// +/// This test requires you to be able to make symlinks. +/// For windows, this may require you to enable developer mode. +fn package_symlink_to_dir() { + if !symlink_supported() { + return; + } + + project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file("bla/Makefile", "all:") + .symlink_dir("bla", "foo") + .build() + .cargo("package -v") + .with_stderr_data(str![[r#" +... +[ARCHIVING] foo/Makefile +... +"#]]) + .run(); +} + +#[cargo_test] +/// Tests if a symlink to ancestor causes filesystem loop error. +/// +/// This test requires you to be able to make symlinks. +/// For windows, this may require you to enable developer mode. +fn filesystem_loop() { + if !symlink_supported() { + return; + } + + project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .symlink_dir("a/b", "a/b/c/d/foo") + .build() + .cargo("package -v") + .with_stderr_data(str![[r#" +... +[WARNING] File system loop found: [ROOT]/foo/a/b/c/d/foo points to an ancestor [ROOT]/foo/a/b +... +"#]]) + .run(); +} + +#[cargo_test] +fn do_not_package_if_repository_is_dirty() { + let p = project().build(); + + // Create a Git repository containing a minimal Rust project. + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // Modify Cargo.toml without committing the change. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + # change + "#, + ); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +Cargo.toml + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + + // cd to `src` and cargo report relative paths. + p.cargo("package") + .cwd(p.root().join("src")) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +../Cargo.toml + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); +} + +#[cargo_test] +fn dirty_ignored() { + // Cargo warns about an ignored file that will be published. + let (p, repo) = git::new_repo("foo", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "foo" + documentation = "foo" + include = ["src", "build"] + "#, + ) + .file("src/lib.rs", "") + .file(".gitignore", "build") + }); + // Example of adding a file that is confusingly ignored by an overzealous + // gitignore rule. + p.change_file("src/build/mod.rs", ""); + p.cargo("package --list") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +src/build/mod.rs + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + // Add the ignored file and make sure it is included. + let mut index = t!(repo.index()); + t!(index.add_path(Path::new("src/build/mod.rs"))); + t!(index.write()); + git::commit(&repo); + p.cargo("package --list") + .with_stderr_data("") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/build/mod.rs +src/lib.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn vcs_status_check_for_each_workspace_member() { + // Cargo checks VCS status separately for each workspace member. + // This ensure one file changed in a package won't affect the other. + // Since the dirty bit in .cargo_vcs_info.json is just for advisory purpose, + // We may change the meaning of it in the future. + let (p, repo) = git::new_repo("foo", |p| { + p.file( + "Cargo.toml", + r#" + [workspace] + members = ["isengard", "mordor"] + "#, + ) + .file("hobbit", "...") + .file( + "isengard/Cargo.toml", + r#" + [package] + name = "isengard" + edition = "2015" + homepage = "saruman" + description = "saruman" + license = "MIT" + "#, + ) + .file("isengard/src/lib.rs", "") + .file( + "mordor/Cargo.toml", + r#" + [package] + name = "mordor" + edition = "2015" + homepage = "sauron" + description = "sauron" + license = "MIT" + "#, + ) + .file("mordor/src/lib.rs", "") + }); + git::commit(&repo); + + p.change_file( + "Cargo.toml", + r#" + [workspace] + members = ["isengard", "mordor"] + [workspace.package] + edition = "2021" + "#, + ); + // Dirty file outside won't affect packaging. + p.change_file("hobbit", "changed!"); + p.change_file("mordor/src/lib.rs", "changed!"); + p.change_file("mordor/src/main.rs", "fn main() {}"); + + // Ensure dirty files be reported only for one affected package. + p.cargo("package --workspace --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] isengard v0.0.0 ([ROOT]/foo/isengard) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[ERROR] 2 files in the working directory contain changes that were not yet committed into git: + +mordor/src/lib.rs +mordor/src/main.rs + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + + // Ensure only dirty package be recorded as dirty. + p.cargo("package --workspace --no-verify --allow-dirty") + .with_stderr_data(str![[r#" +[PACKAGING] isengard v0.0.0 ([ROOT]/foo/isengard) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] mordor v0.0.0 ([ROOT]/foo/mordor) +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/isengard-0.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "isengard-0.0.0.crate", + &[ + ".cargo_vcs_info.json", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "Cargo.lock", + ], + [( + ".cargo_vcs_info.json", + // No change within `isengard/`, so not dirty at all. + str![[r#" +{ + "git": { + "sha1": "[..]" + }, + "path_in_vcs": "isengard" +} +"#]] + .is_json(), + )], + ); + + let f = File::open(&p.root().join("target/package/mordor-0.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "mordor-0.0.0.crate", + &[ + ".cargo_vcs_info.json", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "src/main.rs", + "Cargo.lock", + ], + [( + ".cargo_vcs_info.json", + // Dirty bit is recorded. + str![[r#" +{ + "git": { + "dirty": true, + "sha1": "[..]" + }, + "path_in_vcs": "mordor" +} +"#]] + .is_json(), + )], + ); +} + +#[cargo_test] +fn dirty_file_outside_pkg_root_considered_dirty() { + if !symlink_supported() { + return; + } + let main_outside_pkg_root = paths::root().join("main.rs"); + let (p, repo) = git::new_repo("foo", |p| { + p.file( + "Cargo.toml", + r#" + [workspace] + members = ["isengard"] + resolver = "2" + [workspace.package] + edition = "2015" + "#, + ) + .file("lib.rs", r#"compile_error!("you shall not pass")"#) + .file("LICENSE", "before") + .file("README.md", "before") + .file( + "isengard/Cargo.toml", + r#" + [package] + name = "isengard" + edition.workspace = true + homepage = "saruman" + description = "saruman" + license-file = "../LICENSE" + "#, + ) + .file("original-dir/file", "before") + .symlink("lib.rs", "isengard/src/lib.rs") + .symlink("README.md", "isengard/README.md") + .file(&main_outside_pkg_root, "fn main() {}") + .symlink(&main_outside_pkg_root, "isengard/src/main.rs") + .symlink_dir("original-dir", "isengard/symlink-dir") + }); + git::commit(&repo); + + // Changing files outside pkg root under situations below should be treated + // as dirty. `cargo package` is expected to fail on VCS stastus check. + // + // * Changes in files outside package root that source files symlink to + p.change_file("README.md", "after"); + p.change_file("lib.rs", "pub fn after() {}"); + p.change_file("original-dir/file", "after"); + // * Changes in files outside pkg root that `license-file`/`readme` point to + p.change_file("LICENSE", "after"); + // * When workspace inheritance is involved and changed + p.change_file( + "Cargo.toml", + r#" + [workspace] + members = ["isengard"] + resolver = "2" + [workspace.package] + edition = "2021" + "#, + ); + // Changes in files outside git workdir won't affect vcs status check + p.change_file( + &main_outside_pkg_root, + r#"fn main() { eprintln!("after"); }"#, + ); + + // Ensure dirty files be reported. + p.cargo("package --workspace --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] 4 files in the working directory contain changes that were not yet committed into git: + +LICENSE +README.md +lib.rs +original-dir/file + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); + + p.cargo("package --workspace --no-verify --allow-dirty") + .with_stderr_data(str![[r#" +[PACKAGING] isengard v0.0.0 ([ROOT]/foo/isengard) +[PACKAGED] 9 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); + + let cargo_toml = str![[r##" +... +[package] +edition = "2021" +... + +"##]]; + + let f = File::open(&p.root().join("target/package/isengard-0.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "isengard-0.0.0.crate", + &[ + ".cargo_vcs_info.json", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "src/main.rs", + "symlink-dir/file", + "Cargo.lock", + "LICENSE", + "README.md", + ], + [ + ("src/lib.rs", str!["pub fn after() {}"]), + ("src/main.rs", str![r#"fn main() { eprintln!("after"); }"#]), + ("symlink-dir/file", str!["after"]), + ("README.md", str!["after"]), + ("LICENSE", str!["after"]), + ("Cargo.toml", cargo_toml), + ], + ); +} + +#[cargo_test] +fn issue_13695_allow_dirty_vcs_info() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "foo" + documentation = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let repo = git::init(&p.root()); + // Initial commit, with no files added. + git::commit(&repo); + + // Allowing a dirty worktree results in the vcs file still being included. + p.cargo("package --allow-dirty").run(); + + let f = File::open(&p.root().join("target/package/foo-0.1.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.1.0.crate", + &[ + ".cargo_vcs_info.json", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "Cargo.lock", + ], + [( + ".cargo_vcs_info.json", + str![[r#" +{ + "git": { + "dirty": true, + "sha1": "[..]" + }, + "path_in_vcs": "" +} +"#]] + .is_json(), + )], + ); + + // Listing provides a consistent result. + p.cargo("package --list --allow-dirty") + .with_stderr_data("") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/lib.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn issue_13695_allowing_dirty_vcs_info_but_clean() { + let p = project().build(); + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "foo" + documentation = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Allowing a dirty worktree despite it being clean. + p.cargo("package --allow-dirty").run(); + + let f = File::open(&p.root().join("target/package/foo-0.1.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.1.0.crate", + &[ + ".cargo_vcs_info.json", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "Cargo.lock", + ], + [( + ".cargo_vcs_info.json", + str![[r#" +{ + "git": { + "sha1": "[..]" + }, + "path_in_vcs": "" +} +"#]] + .is_json(), + )], + ); +} + +#[cargo_test] +fn issue_14354_allowing_dirty_bare_commit() { + let p = project().build(); + // Init a bare commit git repo + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "foo" + documentation = "foo" + "#, + ) + .file("src/lib.rs", ""); + + p.cargo("package --allow-dirty").run(); + + let f = File::open(&p.root().join("target/package/foo-0.1.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + (), + ); +} + +#[cargo_test] +fn generated_manifest() { + registry::alt_init(); + Package::new("abc", "1.0.0").publish(); + Package::new("def", "1.0.0").alternative(true).publish(); + Package::new("ghi", "1.0.0").publish(); + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + + [package.metadata] + foo = 'bar' + + [workspace] + + [dependencies] + bar = { path = "bar", version = "0.1" } + def = { version = "1.0", registry = "alternative" } + ghi = "1.0" + abc = "1.0" + "#, + ) + .file("src/main.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("package --no-verify").run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + let rewritten_toml = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +exclude = ["*.txt"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +readme = false +license = "MIT" + +[package.metadata] +foo = "bar" + +[[bin]] +name = "foo" +path = "src/main.rs" + +[dependencies.abc] +version = "1.0" + +[dependencies.bar] +version = "0.1" + +[dependencies.def] +version = "1.0" +registry-index = "[ROOTURL]/alternative-registry" + +[dependencies.ghi] +version = "1.0" + +"##]]; + + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [("Cargo.toml", rewritten_toml)], + ); +} + +#[cargo_test] +fn ignore_workspace_specifier() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + authors = [] + + [workspace] + + [dependencies] + bar = { path = "bar", version = "0.1" } + "#, + ) + .file("src/main.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("package --no-verify").cwd("bar").run(); + + let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap(); + let rewritten_toml = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "bar" +version = "0.1.0" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false + +[lib] +name = "bar" +path = "src/lib.rs" + +"##]]; + validate_crate_contents( + f, + "bar-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [("Cargo.toml", rewritten_toml)], + ); +} + +#[cargo_test] +fn package_two_kinds_of_deps() { + Package::new("other", "1.0.0").publish(); + Package::new("other1", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + other = "1.0" + other1 = { version = "1.0" } + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("package --no-verify").run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn package_public_dep() { + Package::new("bar", "1.0.0").publish(); + Package::new("baz", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + &format! { + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = {{ version = "1.0.0", public = true }} + + [target.{host}.dependencies] + baz = {{ version = "1.0.0", public = true }} + "#, + host = rustc_host() + }, + ) + .file("src/main.rs", "fn main() {}") + .build(); + let rewritten_toml = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false + +[[bin]] +name = "foo" +path = "src/main.rs" + +[dependencies.bar] +version = "1.0.0" + +[target.[HOST_TARGET].dependencies.baz] +version = "1.0.0" + +"##]]; + verify(&p, "package", rewritten_toml); + + let rewritten_toml = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false + +[[bin]] +name = "foo" +path = "src/main.rs" + +[dependencies.bar] +version = "1.0.0" +public = true + +[target.[HOST_TARGET].dependencies.baz] +version = "1.0.0" +public = true + +"##]]; + verify(&p, "package -Zpublic-dependency", rewritten_toml); + + fn verify(p: &cargo_test_support::Project, cmd: &str, rewritten_toml: impl IntoData) { + p.cargo(cmd) + .masquerade_as_nightly_cargo(&["public-dependency"]) + .run(); + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], + [("Cargo.toml", rewritten_toml)], + ); + } +} + +#[cargo_test] +fn test_edition() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition"] + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2018" + "#, + ) + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +... +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]--edition=2018 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn edition_with_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "2018" + + [package.metadata.docs.rs] + features = ["foobar"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package").run(); +} + +#[cargo_test] +fn test_edition_malformed() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "chicken" + "#, + ) + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse the `edition` key + +Caused by: + supported edition values are `2015`, `2018`, `2021`, or `2024`, but `chicken` is unknown + +"#]]) + .run(); +} + +#[cargo_test] +fn test_edition_from_the_future() { + let p = project() + .file( + "Cargo.toml", + r#"[package] + edition = "2038" + name = "foo" + version = "99.99.99" + authors = [] + "#, + ) + .file("src/main.rs", r#""#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to parse the `edition` key + +Caused by: + this version of Cargo is older than the `2038` edition, and only supports `2015`, `2018`, `2021`, and `2024` editions. + +"#]]) + .run(); +} + +#[cargo_test] +fn do_not_package_if_src_was_modified() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file("dir/foo.txt", "") + .file("bar.txt", "") + .file( + "build.rs", + r#" + use std::fs; + + fn main() { + fs::write("src/generated.txt", + "Hello, world of generated files." + ).expect("failed to create file"); + fs::remove_file("dir/foo.txt").expect("failed to remove file"); + fs::remove_dir("dir").expect("failed to remove dir"); + fs::write("bar.txt", "updated content").expect("failed to update"); + fs::create_dir("new-dir").expect("failed to create dir"); + } + "#, + ) + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] failed to verify package tarball + +Caused by: + Source directory was modified by build.rs during cargo publish. Build scripts should not modify anything outside of OUT_DIR. + Changed: [ROOT]/foo/target/package/foo-0.0.1/bar.txt + Added: [ROOT]/foo/target/package/foo-0.0.1/new-dir + [ROOT]/foo/target/package/foo-0.0.1/src/generated.txt + Removed: [ROOT]/foo/target/package/foo-0.0.1/dir + [ROOT]/foo/target/package/foo-0.0.1/dir/foo.txt + + To proceed despite this, pass the `--no-verify` flag. + +"#]]) + .run(); + + p.cargo("package --no-verify").run(); +} + +#[cargo_test] +fn package_with_select_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("package --features required").run(); +} + +#[cargo_test] +fn package_with_all_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("package --all-features").run(); +} + +#[cargo_test] +fn package_no_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [features] + default = ["required"] + required = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("package --no-default-features") + .with_stderr_data(str![[r#" +... +[ERROR] This crate requires `required` feature! +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn include_cargo_toml_implicit() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + include = ["src/lib.rs"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package --list") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/lib.rs + +"#]]) + .run(); +} + +fn include_exclude_test(include: &str, exclude: &str, files: &[&str], expected: &str) { + let mut pb = project().file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + include = {} + exclude = {} + "#, + include, exclude + ), + ); + for file in files { + pb = pb.file(file, ""); + } + let p = pb.build(); + + p.cargo("package --list") + .with_stderr_data("") + .with_stdout_data(expected) + .run(); + p.root().rm_rf(); +} + +#[cargo_test] +fn package_include_ignore_only() { + // Test with a gitignore pattern that fails to parse with glob. + // This is a somewhat nonsense pattern, but is an example of something git + // allows and glob does not. + assert!(glob::Pattern::new("src/abc**").is_err()); + + include_exclude_test( + r#"["Cargo.toml", "src/abc**", "src/lib.rs"]"#, + "[]", + &["src/lib.rs", "src/abc1.rs", "src/abc2.rs", "src/abc/mod.rs"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + src/abc/mod.rs\n\ + src/abc1.rs\n\ + src/abc2.rs\n\ + src/lib.rs\n\ + ", + ) +} + +#[cargo_test] +fn gitignore_patterns() { + include_exclude_test( + r#"["Cargo.toml", "foo"]"#, // include + "[]", + &["src/lib.rs", "foo", "a/foo", "a/b/foo", "x/foo/y", "bar"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + a/b/foo\n\ + a/foo\n\ + foo\n\ + x/foo/y\n\ + ", + ); + + include_exclude_test( + r#"["Cargo.toml", "/foo"]"#, // include + "[]", + &["src/lib.rs", "foo", "a/foo", "a/b/foo", "x/foo/y", "bar"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + foo\n\ + ", + ); + + include_exclude_test( + "[]", + r#"["foo/"]"#, // exclude + &["src/lib.rs", "foo", "a/foo", "x/foo/y", "bar"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + a/foo\n\ + bar\n\ + foo\n\ + src/lib.rs\n\ + ", + ); + + include_exclude_test( + "[]", + r#"["*.txt", "[ab]", "[x-z]"]"#, // exclude + &[ + "src/lib.rs", + "foo.txt", + "bar/foo.txt", + "other", + "a", + "b", + "c", + "x", + "y", + "z", + ], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + c\n\ + other\n\ + src/lib.rs\n\ + ", + ); + + include_exclude_test( + r#"["Cargo.toml", "**/foo/bar"]"#, // include + "[]", + &["src/lib.rs", "a/foo/bar", "foo", "bar"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + a/foo/bar\n\ + ", + ); + + include_exclude_test( + r#"["Cargo.toml", "foo/**"]"#, // include + "[]", + &["src/lib.rs", "a/foo/bar", "foo/x/y/z"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + foo/x/y/z\n\ + ", + ); + + include_exclude_test( + r#"["Cargo.toml", "a/**/b"]"#, // include + "[]", + &["src/lib.rs", "a/b", "a/x/b", "a/x/y/b"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + a/b\n\ + a/x/b\n\ + a/x/y/b\n\ + ", + ); +} + +#[cargo_test] +fn gitignore_negate() { + include_exclude_test( + r#"["Cargo.toml", "*.rs", "!foo.rs", "\\!important"]"#, // include + "[]", + &["src/lib.rs", "foo.rs", "!important"], + "!important\n\ + Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + src/lib.rs\n\ + ", + ); + + // NOTE: This is unusual compared to git. Git treats `src/` as a + // short-circuit which means rules like `!src/foo.rs` would never run. + // However, because Cargo only works by iterating over *files*, it doesn't + // short-circuit. + include_exclude_test( + r#"["Cargo.toml", "src/", "!src/foo.rs"]"#, // include + "[]", + &["src/lib.rs", "src/foo.rs"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + src/lib.rs\n\ + ", + ); + + include_exclude_test( + r#"["Cargo.toml", "src/*.rs", "!foo.rs"]"#, // include + "[]", + &["src/lib.rs", "foo.rs", "src/foo.rs", "src/bar/foo.rs"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + src/lib.rs\n\ + ", + ); + + include_exclude_test( + "[]", + r#"["*.rs", "!foo.rs", "\\!important"]"#, // exclude + &["src/lib.rs", "foo.rs", "!important"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + foo.rs\n\ + ", + ); +} + +#[cargo_test] +fn exclude_dot_files_and_directories_by_default() { + include_exclude_test( + "[]", + "[]", + &["src/lib.rs", ".dotfile", ".dotdir/file"], + "Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + src/lib.rs\n\ + ", + ); + + include_exclude_test( + r#"["Cargo.toml", "src/lib.rs", ".dotfile", ".dotdir/file"]"#, + "[]", + &["src/lib.rs", ".dotfile", ".dotdir/file"], + ".dotdir/file\n\ + .dotfile\n\ + Cargo.lock\n\ + Cargo.toml\n\ + Cargo.toml.orig\n\ + src/lib.rs\n\ + ", + ); +} + +#[cargo_test] +fn empty_readme_path() { + // fail if `readme` is empty. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + readme = "" + license = "MIT" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] readme `` does not appear to exist (relative to `[ROOT]/foo`). +Please update the readme setting in the manifest at `[ROOT]/foo/Cargo.toml`. + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_readme_path() { + // fail if `readme` path is invalid. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + readme = "DOES-NOT-EXIST" + license = "MIT" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] readme `DOES-NOT-EXIST` does not appear to exist (relative to `[ROOT]/foo`). +Please update the readme setting in the manifest at `[ROOT]/foo/Cargo.toml`. + +"#]]) + .run(); +} + +#[cargo_test] +fn readme_or_license_file_is_dir() { + // Test error when `readme` or `license-file` is a directory, not a file. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + readme = "./src" + license-file = "./src" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] license-file `./src` does not appear to exist (relative to `[ROOT]/foo`). +Please update the license-file setting in the manifest at `[ROOT]/foo/Cargo.toml`. +readme `./src` does not appear to exist (relative to `[ROOT]/foo`). +Please update the readme setting in the manifest at `[ROOT]/foo/Cargo.toml`. + +"#]]) + .run(); +} + +#[cargo_test] +fn empty_license_file_path() { + // fail if license-file is empty. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + license-file = "" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no license or license-file. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] license-file `` does not appear to exist (relative to `[ROOT]/foo`). +Please update the license-file setting in the manifest at `[ROOT]/foo/Cargo.toml`. + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_license_file_path() { + // Test warning when license-file points to a non-existent file. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + license-file = "does-not-exist" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] license-file `does-not-exist` does not appear to exist (relative to `[ROOT]/foo`). +Please update the license-file setting in the manifest at `[ROOT]/foo/Cargo.toml`. + +"#]]) + .run(); +} + +#[cargo_test] +fn license_file_implicit_include() { + // license-file should be automatically included even if not listed. + let p = git::new("foo", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + license-file = "subdir/LICENSE" + description = "foo" + homepage = "foo" + include = ["src"] + "#, + ) + .file("src/lib.rs", "") + .file("subdir/LICENSE", "license text") + }); + + p.cargo("package --list") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/lib.rs +subdir/LICENSE + +"#]]) + .with_stderr_data("") + .run(); + + p.cargo("package --no-verify -v") + .with_stderr_data(str![[r#" +[PACKAGING] foo v1.0.0 ([ROOT]/foo) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] src/lib.rs +[ARCHIVING] subdir/LICENSE +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); + let f = File::open(&p.root().join("target/package/foo-1.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-1.0.0.crate", + &[ + ".cargo_vcs_info.json", + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "subdir/LICENSE", + "src/lib.rs", + ], + [("subdir/LICENSE", "license text")], + ); +} + +#[cargo_test] +fn relative_license_included() { + // license-file path outside of package will copy into root. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + license-file = "../LICENSE" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "") + .file("../LICENSE", "license text") + .build(); + + p.cargo("package --list") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +LICENSE +src/lib.rs + +"#]]) + .with_stderr_data("") + .run(); + + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v1.0.0 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v1.0.0 ([ROOT]/foo) +[COMPILING] foo v1.0.0 ([ROOT]/foo/target/package/foo-1.0.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + let f = File::open(&p.root().join("target/package/foo-1.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-1.0.0.crate", + &[ + "Cargo.toml", + "Cargo.toml.orig", + "LICENSE", + "src/lib.rs", + "Cargo.lock", + ], + [("LICENSE", "license text")], + ); + let manifest = + std::fs::read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml")).unwrap(); + assert!(manifest.contains("license-file = \"LICENSE\"")); + let orig = + std::fs::read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml.orig")).unwrap(); + assert!(orig.contains("license-file = \"../LICENSE\"")); +} + +#[cargo_test] +fn relative_license_include_collision() { + // Can't copy a relative license-file if there is a file with that name already. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2015" + license-file = "../LICENSE" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "") + .file("../LICENSE", "outer license") + .file("LICENSE", "inner license") + .build(); + + p.cargo("package --list") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +LICENSE +src/lib.rs + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] license-file `../LICENSE` appears to be a path outside of the package, but there is already a file named `LICENSE` in the root of the package. The archived crate will contain the copy in the root of the package. Update the license-file to point to the path relative to the root of the package to remove this warning. + +"#]]) + .run(); + + p.cargo("package").with_stderr_data(str![[r#" +[WARNING] license-file `../LICENSE` appears to be a path outside of the package, but there is already a file named `LICENSE` in the root of the package. The archived crate will contain the copy in the root of the package. Update the license-file to point to the path relative to the root of the package to remove this warning. +[PACKAGING] foo v1.0.0 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v1.0.0 ([ROOT]/foo) +[COMPILING] foo v1.0.0 ([ROOT]/foo/target/package/foo-1.0.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); + let f = File::open(&p.root().join("target/package/foo-1.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-1.0.0.crate", + &[ + "Cargo.toml", + "Cargo.toml.orig", + "LICENSE", + "src/lib.rs", + "Cargo.lock", + ], + [("LICENSE", "inner license")], + ); + let manifest = read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml")).unwrap(); + assert!(manifest.contains("license-file = \"LICENSE\"")); + let orig = read_to_string(p.root().join("target/package/foo-1.0.0/Cargo.toml.orig")).unwrap(); + assert!(orig.contains("license-file = \"../LICENSE\"")); +} + +#[cargo_test] +#[cfg(not(windows))] // Don't want to create invalid files on Windows. +fn package_restricted_windows() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + license = "MIT" + description = "foo" + homepage = "foo" + "#, + ) + .file("src/lib.rs", "pub mod con;\npub mod aux;") + .file("src/con.rs", "pub fn f() {}") + .file("src/aux/mod.rs", "pub fn f() {}") + .build(); + + p.cargo("package") + // use unordered here because the order of the warning is different on each platform. + .with_stderr_data( + str![[r#" +[WARNING] file src/con.rs is a reserved Windows filename, it will not work on Windows platforms +[WARNING] file src/aux/mod.rs is a reserved Windows filename, it will not work on Windows platforms +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.1.0 ([ROOT]/foo) +[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn finds_git_in_parent() { + // Test where `Cargo.toml` is not in the root of the git repo. + let repo_path = paths::root().join("repo"); + fs::create_dir(&repo_path).unwrap(); + let p = project() + .at("repo/foo") + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "") + .build(); + let repo = git::init(&repo_path); + git::add(&repo); + git::commit(&repo); + p.change_file("ignoreme", ""); + p.change_file("ignoreme2", ""); + p.cargo("package --list --allow-dirty") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +ignoreme +ignoreme2 +src/lib.rs + +"#]]) + .run(); + + p.change_file(".gitignore", "ignoreme"); + p.cargo("package --list --allow-dirty") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +.gitignore +Cargo.lock +Cargo.toml +Cargo.toml.orig +ignoreme2 +src/lib.rs + +"#]]) + .run(); + + fs::write(repo_path.join(".gitignore"), "ignoreme2").unwrap(); + p.cargo("package --list --allow-dirty") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +.gitignore +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/lib.rs + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(windows)] +fn reserved_windows_name() { + // If we are running on a version of Windows that allows these reserved filenames, + // skip this test. + if paths::windows_reserved_names_are_allowed() { + return; + } + + Package::new("bar", "1.0.0") + .file("src/lib.rs", "pub mod aux;") + .file("src/aux.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies] + bar = "1.0.0" + "#, + ) + .file("src/main.rs", "extern crate bar;\nfn main() { }") + .build(); + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] failed to verify package tarball + +Caused by: + failed to download replaced source registry `crates-io` + +Caused by: + failed to unpack package `bar v1.0.0 (registry `dummy-registry`)` + +Caused by: + failed to unpack entry at `bar-1.0.0/src/aux.rs` + +Caused by: + `bar-1.0.0/src/aux.rs` appears to contain a reserved Windows path, it cannot be extracted on Windows + +Caused by: + failed to unpack `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/src/aux.rs` + +Caused by: + failed to unpack `bar-1.0.0/src/aux.rs` into `[ROOT]/home/.cargo/registry/src/-[HASH]/bar-1.0.0/src/aux.rs` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn list_with_path_and_lock() { + // Allow --list even for something that isn't packageable. + + // Init an empty registry because a versionless path dep will search for + // the package on crates.io. + registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + license = "MIT" + description = "foo" + homepage = "foo" + + [dependencies] + bar = {path="bar"} + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("package --list") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] all dependencies must have a version specified when packaging. +dependency `bar` does not specify a version +Note: The packaged dependency will use the version from crates.io, +the `path` specification will be removed from the dependency declaration. + +"#]]) + .run(); +} + +#[cargo_test] +fn long_file_names() { + // Filenames over 100 characters require a GNU extension tarfile. + // See #8453. + + registry::init(); + let long_name = concat!( + "012345678901234567890123456789012345678901234567890123456789", + "012345678901234567890123456789012345678901234567890123456789", + "012345678901234567890123456789012345678901234567890123456789" + ); + if cfg!(windows) { + // Long paths on Windows require a special registry entry that is + // disabled by default (even on Windows 10). + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + // If the directory where Cargo runs happens to be more than 80 characters + // long, then it will bump into this limit. + // + // First create a directory to account for various paths Cargo will + // be using in the target directory (such as "target/package/foo-0.1.0"). + let test_path = paths::root().join("test-dir-probe-long-path-support"); + test_path.mkdir_p(); + let test_path = test_path.join(long_name); + if let Err(e) = File::create(&test_path) { + // write to stderr directly to avoid output from being captured + // and always display text, even without --nocapture + use std::io::Write; + writeln!( + std::io::stderr(), + "\nSkipping long_file_names test, this OS or filesystem does not \ + appear to support long file paths: {:?}\n{:?}", + e, + test_path + ) + .unwrap(); + return; + } + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + license = "MIT" + description = "foo" + homepage = "foo" + + [dependencies] + "#, + ) + .file(long_name, "something") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("package").run(); + p.cargo("package --list").with_stdout_data(str![[r#" +012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]).run(); +} + +#[cargo_test] +fn reproducible_output() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("package").run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + let decoder = GzDecoder::new(f); + let mut archive = Archive::new(decoder); + for ent in archive.entries().unwrap() { + let ent = ent.unwrap(); + println!("checking {:?}", ent.path()); + let header = ent.header(); + assert_eq!(header.mode().unwrap(), 0o644); + assert!(header.mtime().unwrap() != 0); + assert_eq!(header.username().unwrap().unwrap(), ""); + assert_eq!(header.groupname().unwrap().unwrap(), ""); + } +} + +#[cargo_test] +fn package_with_resolver_and_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + resolver = '2' + + [package.metadata.docs.rs] + all-features = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("package").run(); +} + +#[cargo_test] +fn deleted_git_working_tree() { + // When deleting a file, but not staged, cargo should ignore the file. + let (p, repo) = git::new_repo("foo", |p| { + p.file("src/lib.rs", "").file("src/main.rs", "fn main() {}") + }); + p.root().join("src/lib.rs").rm_rf(); + p.cargo("package --allow-dirty --list") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("package --allow-dirty").run(); + let mut index = t!(repo.index()); + t!(index.remove(Path::new("src/lib.rs"), 0)); + t!(index.write()); + p.cargo("package --allow-dirty --list") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("package --allow-dirty").run(); +} + +#[cargo_test] +fn package_in_workspace_not_found() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "bar" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "baz" + "#, + ) + .file("baz/src/main.rs", "fn main() {}") + .build(); + + p.cargo("package -p doesnt-exist") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `doesnt-exist` did not match any packages + +"#]]) + .run(); +} + +#[cargo_test] +fn in_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "bar" + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("package --workspace") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + assert!(p.root().join("target/package/bar-0.0.1.crate").is_file()); +} + +#[cargo_test] +fn workspace_noconflict_readme() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("README.md", "workspace readme") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + repository = "https://github.com/bar/bar" + authors = [] + license = "MIT" + description = "bar" + readme = "../README.md" + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/example/README.md", "# example readmdBar") + .build(); + + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar) +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_conflict_readme() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("README.md", "workspace readme") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + repository = "https://github.com/bar/bar" + authors = [] + license = "MIT" + description = "bar" + readme = "../README.md" + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/README.md", "# workspace member: Bar") + .build(); + + p.cargo("package").with_stderr_data(str![[r#" +[WARNING] readme `../README.md` appears to be a path outside of the package, but there is already a file named `README.md` in the root of the package. The archived crate will contain the copy in the root of the package. Update the readme to point to the path relative to the root of the package to remove this warning. +[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn workspace_overrides_resolver() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2021" + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("package --no-verify -p bar -p baz").run(); + + let f = File::open(&p.root().join("target/package/bar-0.1.0.crate")).unwrap(); + let rewritten_toml = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "bar" +version = "0.1.0" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false +resolver = "1" + +[lib] +name = "bar" +path = "src/lib.rs" + +"##]]; + validate_crate_contents( + f, + "bar-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [("Cargo.toml", rewritten_toml)], + ); + + // When the crate has the same implicit resolver as the workspace it is not overridden + let f = File::open(&p.root().join("target/package/baz-0.1.0.crate")).unwrap(); + let rewritten_toml = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "baz" +version = "0.1.0" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +readme = false + +[lib] +name = "baz" +path = "src/lib.rs" + +"##]]; + validate_crate_contents( + f, + "baz-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [("Cargo.toml", rewritten_toml)], + ); +} + +fn verify_packaged_status_line( + output: cargo_test_support::RawOutput, + num_files: usize, + uncompressed_size: u64, + compressed_size: u64, +) { + use cargo::util::human_readable_bytes; + + let stderr = String::from_utf8(output.stderr).unwrap(); + let mut packaged_lines = stderr + .lines() + .filter(|line| line.trim().starts_with("Packaged")); + let packaged_line = packaged_lines + .next() + .expect("`Packaged` status line should appear in stderr"); + assert!( + packaged_lines.next().is_none(), + "Only one `Packaged` status line should appear in stderr" + ); + let size_info = packaged_line.trim().trim_start_matches("Packaged").trim(); + let uncompressed = human_readable_bytes(uncompressed_size); + let compressed = human_readable_bytes(compressed_size); + let expected = format!( + "{} files, {:.1}{} ({:.1}{} compressed)", + num_files, uncompressed.0, uncompressed.1, compressed.0, compressed.1 + ); + assert_eq!(size_info, expected); +} + +#[cargo_test] +fn basic_filesizes() { + let cargo_toml_orig_contents = r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + homepage = "https://example.com/" + "#; + let main_rs_contents = r#"fn main() { println!("🦀"); }"#; + let cargo_toml_contents = format!( + r#"{} +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +exclude = ["*.txt"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "https://example.com/" +readme = false +license = "MIT" + +[[bin]] +name = "foo" +path = "src/main.rs" +"#, + cargo::core::manifest::MANIFEST_PREAMBLE + ); + let cargo_lock_contents = r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "foo" +version = "0.0.1" +"#; + let p = project() + .file("Cargo.toml", cargo_toml_orig_contents) + .file("src/main.rs", main_rs_contents) + .file("src/bar.txt", "Ignored text file contents") // should be ignored when packaging + .build(); + + let uncompressed_size = (cargo_toml_orig_contents.len() + + main_rs_contents.len() + + cargo_toml_contents.len() + + cargo_lock_contents.len()) as u64; + let output = p.cargo("package").run(); + + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + let compressed_size = f.metadata().unwrap().len(); + verify_packaged_status_line(output, 4, uncompressed_size, compressed_size); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [ + ("Cargo.lock", cargo_lock_contents), + ("Cargo.toml", &cargo_toml_contents), + ("Cargo.toml.orig", cargo_toml_orig_contents), + ("src/main.rs", main_rs_contents), + ], + ); +} + +#[cargo_test] +fn larger_filesizes() { + let cargo_toml_orig_contents = r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "https://example.com/" + "#; + let lots_of_crabs = std::iter::repeat("🦀").take(1337).collect::(); + let main_rs_contents = format!(r#"fn main() {{ println!("{}"); }}"#, lots_of_crabs); + let bar_txt_contents = "This file is relatively uncompressible, to increase the compressed + package size beyond 1KiB. + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt + ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + laborum."; + let cargo_toml_contents = format!( + r#"{} +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "https://example.com/" +readme = false +license = "MIT" + +[[bin]] +name = "foo" +path = "src/main.rs" +"#, + cargo::core::manifest::MANIFEST_PREAMBLE + ); + let cargo_lock_contents = r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "foo" +version = "0.0.1" +"#; + let p = project() + .file("Cargo.toml", cargo_toml_orig_contents) + .file("src/main.rs", &main_rs_contents) + .file("src/bar.txt", bar_txt_contents) + .build(); + + let uncompressed_size = (cargo_toml_orig_contents.len() + + main_rs_contents.len() + + cargo_toml_contents.len() + + cargo_lock_contents.len() + + bar_txt_contents.len()) as u64; + + let output = p.cargo("package").run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/bar.txt +src/main.rs + +"#]]) + .run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + let compressed_size = f.metadata().unwrap().len(); + verify_packaged_status_line(output, 5, uncompressed_size, compressed_size); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/bar.txt", + "src/main.rs", + ], + [ + ("Cargo.lock", cargo_lock_contents), + ("Cargo.toml", &cargo_toml_contents), + ("Cargo.toml.orig", cargo_toml_orig_contents), + ("src/bar.txt", bar_txt_contents), + ("src/main.rs", &main_rs_contents), + ], + ); +} + +#[cargo_test] +fn symlink_filesizes() { + if !symlink_supported() { + return; + } + + let cargo_toml_orig_contents = r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + homepage = "https://example.com/" + "#; + let lots_of_crabs = std::iter::repeat("🦀").take(1337).collect::(); + let main_rs_contents = format!(r#"fn main() {{ println!("{}"); }}"#, lots_of_crabs); + let bar_txt_contents = "This file is relatively uncompressible, to increase the compressed + package size beyond 1KiB. + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt + ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est + laborum."; + let cargo_toml_contents = format!( + r#"{} +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "https://example.com/" +readme = false +license = "MIT" + +[[bin]] +name = "foo" +path = "src/main.rs" +"#, + cargo::core::manifest::MANIFEST_PREAMBLE + ); + let cargo_lock_contents = r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "foo" +version = "0.0.1" +"#; + + let p = project() + .file("Cargo.toml", cargo_toml_orig_contents) + .file("src/main.rs", &main_rs_contents) + .file("bla/bar.txt", bar_txt_contents) + .symlink("src/main.rs", "src/main.rs.bak") + .symlink_dir("bla", "foo") + .build(); + + let uncompressed_size = (cargo_toml_orig_contents.len() + + main_rs_contents.len() * 2 + + cargo_toml_contents.len() + + cargo_lock_contents.len() + + bar_txt_contents.len() * 2) as u64; + + let output = p.cargo("package").run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +bla/bar.txt +foo/bar.txt +src/main.rs +src/main.rs.bak + +"#]]) + .run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 7 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + let compressed_size = f.metadata().unwrap().len(); + verify_packaged_status_line(output, 7, uncompressed_size, compressed_size); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "bla/bar.txt", + "foo/bar.txt", + "src/main.rs", + "src/main.rs.bak", + ], + [ + ("Cargo.lock", cargo_lock_contents), + ("Cargo.toml", &cargo_toml_contents), + ("Cargo.toml.orig", cargo_toml_orig_contents), + ("bla/bar.txt", bar_txt_contents), + ("foo/bar.txt", bar_txt_contents), + ("src/main.rs", &main_rs_contents), + ("src/main.rs.bak", &main_rs_contents), + ], + ); +} + +#[cargo_test] +#[cfg(windows)] // windows is the platform that is most consistently configured for case insensitive filesystems +fn normalize_case() { + let p = project() + .file("Build.rs", r#"fn main() { println!("hello"); }"#) + .file("src/Main.rs", r#"fn main() { println!("hello"); }"#) + .file("src/lib.rs", "") + .file("src/bar.txt", "") // should be ignored when packaging + .file("Examples/ExampleFoo.rs", "") + .file("Tests/ExplicitPath.rs", "") + .build(); + // Workaround `project()` making a `Cargo.toml` on our behalf + std::fs::remove_file(p.root().join("Cargo.toml")).unwrap(); + std::fs::write( + p.root().join("cargo.toml"), + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2018" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + + [[test]] + name = "explicitpath" + path = "tests/explicitpath.rs" + "#, + ) + .unwrap(); + + p.cargo("package").with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring `package.build` as `build.rs` is not included in the published package +[WARNING] ignoring binary `foo` as `src/main.rs` is not included in the published package +[WARNING] ignoring example `ExampleFoo` as `examples/ExampleFoo.rs` is not included in the published package +[WARNING] ignoring test `ExplicitPath` as `tests/ExplicitPath.rs` is not included in the published package +[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package +[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Build.rs +Cargo.lock +Cargo.toml +Cargo.toml.orig +Examples/ExampleFoo.rs +Tests/ExplicitPath.rs +src/Main.rs +src/lib.rs + +"#]]) + .run(); + p.cargo("package").with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring `package.build` as `build.rs` is not included in the published package +[WARNING] ignoring binary `foo` as `src/main.rs` is not included in the published package +[WARNING] ignoring example `ExampleFoo` as `examples/ExampleFoo.rs` is not included in the published package +[WARNING] ignoring test `ExplicitPath` as `tests/ExplicitPath.rs` is not included in the published package +[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package +[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "Build.rs", + "src/Main.rs", + "src/lib.rs", + "Examples/ExampleFoo.rs", + "Tests/ExplicitPath.rs", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "foo" +version = "0.0.1" +authors = [] +build = false +exclude = ["*.txt"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +"##]], + )], + ); +} + +#[cargo_test] +#[cfg(target_os = "linux")] // linux is generally configured to be case sensitive +fn mixed_case() { + let manifest = r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + exclude = ["*.txt"] + license = "MIT" + description = "foo" + "#; + let p = project() + .file("Cargo.toml", manifest) + .file("cargo.toml", manifest) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file("src/bar.txt", "") // should be ignored when packaging + .build(); + + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + (), + ); +} + +#[cargo_test] +fn versionless_package() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + edition = "2015" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("package") + .with_stderr_data(str![[r#" +[WARNING] manifest has no license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.0 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.0 ([ROOT]/foo) +[COMPILING] foo v0.0.0 ([ROOT]/foo/target/package/foo-0.0.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.0.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + (), + ); +} + +#[cargo_test] +fn include_files_called_target_project() { + // https://github.com/rust-lang/cargo/issues/12790 + // files and folders called "target" should be included, unless they're the actual target directory + let p = init_and_add_inner_target(project()) + .file("target/foo.txt", "") + .build(); + + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +data/not_target +data/target +derp/not_target/foo.txt +derp/target/foo.txt +src/main.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn include_files_called_target_git() { + // https://github.com/rust-lang/cargo/issues/12790 + // files and folders called "target" should be included, unless they're the actual target directory + let (p, repo) = git::new_repo("foo", |p| init_and_add_inner_target(p)); + // add target folder but not committed. + _ = fs::create_dir(p.build_dir()).unwrap(); + _ = fs::write(p.build_dir().join("foo.txt"), "").unwrap(); + p.cargo("package -l") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +data/not_target +data/target +derp/not_target/foo.txt +derp/target/foo.txt +src/main.rs + +"#]]) + .run(); + + // if target is committed, it should be included. + git::add(&repo); + git::commit(&repo); + p.cargo("package -l") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +data/not_target +data/target +derp/not_target/foo.txt +derp/target/foo.txt +src/main.rs +target/foo.txt + +"#]]) + .run(); + + // Untracked files shouldn't be included, if they are also ignored. + _ = fs::write(repo.workdir().unwrap().join(".gitignore"), "target/").unwrap(); + git::add(&repo); + git::commit(&repo); + _ = fs::write(p.build_dir().join("untracked.txt"), "").unwrap(); + p.cargo("package -l") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +.gitignore +Cargo.lock +Cargo.toml +Cargo.toml.orig +data/not_target +data/target +derp/not_target/foo.txt +derp/target/foo.txt +src/main.rs +target/foo.txt + +"#]]) + .run(); +} + +fn init_and_add_inner_target(p: ProjectBuilder) -> ProjectBuilder { + p.file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + // file called target, should be included + .file("data/target", "") + .file("data/not_target", "") + // folder called target, should be included + .file("derp/target/foo.txt", "") + .file("derp/not_target/foo.txt", "") +} + +#[cargo_test] +fn build_script_outside_pkg_root() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + authors = [] + build = "../t_custom_build/custom_build.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + // custom_build.rs does not exist + p.cargo("package -l") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] the source file of build script doesn't appear to exist. +This may cause issue during packaging, as modules resolution and resources included via macros are often relative to the path of source files. +Please update the `build` setting in the manifest at `[ROOT]/foo/Cargo.toml` and point to a path inside the root of the package. + +"#]]) + .run(); + + // custom_build.rs outside the package root + let custom_build_root = paths::root().join("t_custom_build"); + _ = fs::create_dir(&custom_build_root).unwrap(); + _ = fs::write(&custom_build_root.join("custom_build.rs"), "fn main() {}"); + p.cargo("package -l") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[ERROR] the source file of build script doesn't appear to be a path inside of the package. +It is at `[ROOT]/t_custom_build/custom_build.rs`, whereas the root the package is `[ROOT]/foo`. +This may cause issue during packaging, as modules resolution and resources included via macros are often relative to the path of source files. +Please update the `build` setting in the manifest at `[ROOT]/foo/Cargo.toml` and point to a path inside the root of the package. + +"#]]) + .run(); +} + +#[cargo_test] +fn symlink_manifest_path() { + // Test `cargo install --manifest-path` pointing through a symlink. + if !symlink_supported() { + return; + } + let p = git::new("foo", |p| { + p.file("Cargo.toml", &basic_manifest("foo", "1.0.0")) + .file("src/main.rs", "fn main() {}") + // Triggers discover_git_and_list_files for detecting changed files. + .file("build.rs", "fn main() {}") + }); + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(windows)] + use std::os::windows::fs::symlink_dir as symlink; + + let foo_symlink = paths::root().join("foo-symlink"); + t!(symlink(p.root(), &foo_symlink)); + + cargo_process("package --no-verify --manifest-path") + .arg(foo_symlink.join("Cargo.toml")) + .with_stderr_data(str![[r#" +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v1.0.0 ([ROOT]/foo-symlink) +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(windows)] +fn normalize_paths() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + readme = ".\\docs\\README.md" + license-file = ".\\docs\\LICENSE" + build = ".\\src\\build.rs" + + [lib] + path = ".\\src\\lib.rs" + + [[bin]] + name = "foo" + path = ".\\src\\bin\\foo\\main.rs" + + [[example]] + name = "example_foo" + path = ".\\examples\\example_foo.rs" + + [[test]] + name = "test_foo" + path = ".\\tests\\test_foo.rs" + + [[bench]] + name = "bench_foo" + path = ".\\benches\\bench_foo.rs" + "#, + ) + .file("src/lib.rs", "") + .file("docs/README.md", "") + .file("docs/LICENSE", "") + .file("src/build.rs", "fn main() {}") + .file("src/bin/foo/main.rs", "fn main() {}") + .file("examples/example_foo.rs", "fn main() {}") + .file("tests/test_foo.rs", "fn main() {}") + .file("benches/bench_foo.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 11 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "docs/README.md", + "docs/LICENSE", + "src/build.rs", + "src/bin/foo/main.rs", + "examples/example_foo.rs", + "tests/test_foo.rs", + "benches/bench_foo.rs", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = "src/build.rs" +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = "docs/README.md" +license-file = "docs/LICENSE" + +[lib] +name = "foo" +path = "src/lib.rs" + +[[bin]] +name = "foo" +path = "src/bin/foo/main.rs" + +[[example]] +name = "example_foo" +path = "examples/example_foo.rs" + +[[test]] +name = "test_foo" +path = "tests/test_foo.rs" + +[[bench]] +name = "bench_foo" +path = "benches/bench_foo.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_inferred_build_rs_included() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs", "build.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "build.rs", + "Cargo.lock", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = "build.rs" +include = [ + "src/lib.rs", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_inferred_build_rs_excluded() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring `package.build` as `build.rs` is not included in the published package +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = ["src/lib.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_explicit_build_rs_included() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs", "build.rs"] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "build.rs", + "Cargo.lock", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = "build.rs" +include = [ + "src/lib.rs", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_explicit_build_rs_excluded() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs"] + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring `package.build` as `build.rs` is not included in the published package +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = ["src/lib.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_inferred_lib_included() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/main.rs", "src/lib.rs"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + "src/lib.rs", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = [ + "src/main.rs", + "src/lib.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +[[bin]] +name = "foo" +path = "src/main.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_inferred_lib_excluded() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/main.rs"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring library `foo` as `src/lib.rs` is not included in the published package +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = ["src/main.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[[bin]] +name = "foo" +path = "src/main.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_explicit_lib_included() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/main.rs", "src/lib.rs"] + + [lib] + path = "src/lib.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + "src/lib.rs", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = [ + "src/main.rs", + "src/lib.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +[[bin]] +name = "foo" +path = "src/main.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_explicit_lib_excluded() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/main.rs"] + + [lib] + path = "src/lib.rs" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring library `foo` as `src/lib.rs` is not included in the published package +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = ["src/main.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[[bin]] +name = "foo" +path = "src/main.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_inferred_other_included() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs", "src/bin/foo/main.rs", "examples/example_foo.rs", "tests/test_foo.rs", "benches/bench_foo.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/foo/main.rs", "fn main() {}") + .file("examples/example_foo.rs", "fn main() {}") + .file("tests/test_foo.rs", "fn main() {}") + .file("benches/bench_foo.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "src/bin/foo/main.rs", + "examples/example_foo.rs", + "tests/test_foo.rs", + "benches/bench_foo.rs", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = [ + "src/lib.rs", + "src/bin/foo/main.rs", + "examples/example_foo.rs", + "tests/test_foo.rs", + "benches/bench_foo.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +[[bin]] +name = "foo" +path = "src/bin/foo/main.rs" + +[[example]] +name = "example_foo" +path = "examples/example_foo.rs" + +[[test]] +name = "test_foo" +path = "tests/test_foo.rs" + +[[bench]] +name = "bench_foo" +path = "benches/bench_foo.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_inferred_other_excluded() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/foo/main.rs", "fn main() {}") + .file("examples/example_foo.rs", "fn main() {}") + .file("tests/test_foo.rs", "fn main() {}") + .file("benches/bench_foo.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring binary `foo` as `src/bin/foo/main.rs` is not included in the published package +[WARNING] ignoring example `example_foo` as `examples/example_foo.rs` is not included in the published package +[WARNING] ignoring test `test_foo` as `tests/test_foo.rs` is not included in the published package +[WARNING] ignoring benchmark `bench_foo` as `benches/bench_foo.rs` is not included in the published package +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/lib.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = ["src/lib.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_explicit_other_included() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs", "src/bin/foo/main.rs", "examples/example_foo.rs", "tests/test_foo.rs", "benches/bench_foo.rs"] + + [[bin]] + name = "foo" + + [[example]] + name = "example_foo" + + [[test]] + name = "test_foo" + + [[bench]] + name = "bench_foo" + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/foo/main.rs", "fn main() {}") + .file("examples/example_foo.rs", "fn main() {}") + .file("tests/test_foo.rs", "fn main() {}") + .file("benches/bench_foo.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 8 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "src/bin/foo/main.rs", + "examples/example_foo.rs", + "tests/test_foo.rs", + "benches/bench_foo.rs", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = [ + "src/lib.rs", + "src/bin/foo/main.rs", + "examples/example_foo.rs", + "tests/test_foo.rs", + "benches/bench_foo.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +[[bin]] +name = "foo" +path = "src/bin/foo/main.rs" + +[[example]] +name = "example_foo" +path = "examples/example_foo.rs" + +[[test]] +name = "test_foo" +path = "tests/test_foo.rs" + +[[bench]] +name = "bench_foo" +path = "benches/bench_foo.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn discovery_explicit_other_excluded() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs"] + + [[main]] + name = "foo" + + [[example]] + name = "example_foo" + + [[test]] + name = "test_foo" + + [[bench]] + name = "bench_foo" + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/foo/main.rs", "fn main() {}") + .file("examples/example_foo.rs", "fn main() {}") + .file("tests/test_foo.rs", "fn main() {}") + .file("benches/bench_foo.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[WARNING] ignoring binary `foo` as `src/bin/foo/main.rs` is not included in the published package +[WARNING] ignoring example `example_foo` as `examples/example_foo.rs` is not included in the published package +[WARNING] ignoring test `test_foo` as `tests/test_foo.rs` is not included in the published package +[WARNING] ignoring benchmark `bench_foo` as `benches/bench_foo.rs` is not included in the published package +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/lib.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.0.1" +authors = [] +build = false +include = ["src/lib.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +"##]], + )], + ); +} + +#[cargo_test] +fn deterministic_build_targets() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + + [[example]] + name = "c" + + [[example]] + name = "b" + + [[example]] + name = "a" + "#, + ) + .file("src/lib.rs", "") + .file("examples/z.rs", "fn main() {}") + .file("examples/y.rs", "fn main() {}") + .file("examples/x.rs", "fn main() {}") + .file("examples/c.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("examples/a.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 10 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + "examples/a.rs", + "examples/b.rs", + "examples/c.rs", + "examples/x.rs", + "examples/y.rs", + "examples/z.rs", + ], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "foo" +version = "0.0.1" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "foo" +path = "src/lib.rs" + +[[example]] +name = "a" +path = "examples/a.rs" + +[[example]] +name = "b" +path = "examples/b.rs" + +[[example]] +name = "c" +path = "examples/c.rs" + +[[example]] +name = "x" +path = "examples/x.rs" + +[[example]] +name = "y" +path = "examples/y.rs" + +[[example]] +name = "z" +path = "examples/z.rs" + +"##]], + )], + ); +} + +// A workspace with three projects that depend on one another (level1 -> level2 -> level3). +// level1 is a binary package, to test lockfile generation. +fn workspace_with_local_deps_project() -> Project { + project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2", "level3"] + + [workspace.dependencies] + level2 = { path = "level2", version = "0.0.1" } + "# + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + # Let one dependency also specify features, for the added test coverage when generating package files. + level2 = { workspace = true, features = ["foo"] } + "#, + ) + .file("level1/src/main.rs", "fn main() {}") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + + [features] + foo = [] + + [dependencies] + level3 = { path = "../level3", version = "0.0.1" } + "# + ) + .file("level2/src/lib.rs", "") + .file( + "level3/Cargo.toml", + r#" + [package] + name = "level3" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level3" + repository = "bar" + "#, + ) + .file("level3/src/lib.rs", "") + .build() +} + +#[cargo_test] +fn workspace_with_local_deps() { + let crates_io = registry::init(); + let p = workspace_with_local_deps_project(); + + p.cargo("package") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level3 v0.0.1 ([ROOT]/foo/level3) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2) +[UPDATING] crates.io index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `level3` found + location searched: crates.io index + required by package `level2 v0.0.1 ([ROOT]/foo/level2)` + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_with_local_deps_nightly() { + let crates_io = registry::init(); + let p = workspace_with_local_deps_project(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(crates_io.index_url()) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level3 v0.0.1 ([ROOT]/foo/level3) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] level3 v0.0.1 ([ROOT]/foo/level3) +[COMPILING] level3 v0.0.1 ([ROOT]/foo/target/package/level3-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2) +[UNPACKING] level3 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] level3 v0.0.1 +[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] level1 v0.0.1 ([ROOT]/foo/level1) +[UNPACKING] level2 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] level3 v0.0.1 +[COMPILING] level2 v0.0.1 +[COMPILING] level1 v0.0.1 ([ROOT]/foo/target/package/level1-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let generated_lock = str![[r##" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "level1" +version = "0.0.1" +dependencies = [ + "level2", +] + +[[package]] +name = "level2" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" +dependencies = [ + "level3", +] + +[[package]] +name = "level3" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" + +"##]]; + + let generated_manifest = str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "level1" +version = "0.0.1" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "level1" +readme = false +license = "MIT" +repository = "bar" + +[[bin]] +name = "level1" +path = "src/main.rs" + +[dependencies.level2] +version = "0.0.1" +features = ["foo"] + +"##]]; + + let mut f = File::open(&p.root().join("target/package/level1-0.0.1.crate")).unwrap(); + + validate_crate_contents( + &mut f, + "level1-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [ + ("Cargo.lock", generated_lock), + ("Cargo.toml", generated_manifest), + ], + ); +} + +fn workspace_with_local_deps_packaging_one_fails_project() -> Project { + project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2"] + "#, + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + level2 = { path = "../level2", version = "0.0.1" } + "#, + ) + .file("level1/src/lib.rs", "") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + "#, + ) + .file("level2/src/lib.rs", "") + .build() +} + +#[cargo_test] +fn workspace_with_local_deps_packaging_one_fails() { + let crates_io = registry::init(); + let p = workspace_with_local_deps_packaging_one_fails_project(); + + // We can't package just level1, because there's a dependency on level2. + p.cargo("package -p level1") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] crates.io index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `level2` found + location searched: crates.io index + required by package `level1 v0.0.1 ([ROOT]/foo/level1)` + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_with_local_deps_packaging_one_fails_nightly() { + let crates_io = registry::init(); + let p = workspace_with_local_deps_packaging_one_fails_project(); + + // We can't package just level1, because there's a dependency on level2. + p.cargo("package -p level1 -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] crates.io index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `level2` found + location searched: crates.io index + required by package `level1 v0.0.1 ([ROOT]/foo/level1)` + +"#]]) + .run(); +} + +// Same as workspace_with_local_deps_packaging_one_fails except that we're +// packaging a bin. This fails during lock-file generation instead of during verification. +#[cargo_test] +fn workspace_with_local_deps_packaging_one_bin_fails() { + let crates_io = registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2"] + "#, + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + level2 = { path = "../level2", version = "0.0.1" } + "#, + ) + .file("level1/src/main.rs", "fn main() {}") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + "#, + ) + .file("level2/src/lib.rs", "") + .build(); + + // We can't package just level1, because there's a dependency on level2. + p.cargo("package -p level1 -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] crates.io index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `level2` found + location searched: crates.io index + required by package `level1 v0.0.1 ([ROOT]/foo/level1)` + +"#]]) + .run(); +} + +// Here we don't package the whole workspace, but it succeeds because we package a +// dependency-closed subset. +#[cargo_test] +fn workspace_with_local_deps_packaging_one_with_needed_deps() { + let crates_io = registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2", "level3"] + "#, + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + level2 = { path = "../level2", version = "0.0.1" } + "#, + ) + .file("level1/src/main.rs", "fn main() {}") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + + [dependencies] + level3 = { path = "../level3", version = "0.0.1" } + "#, + ) + .file("level2/src/lib.rs", "") + .file( + "level3/Cargo.toml", + r#" + [package] + name = "level3" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level3" + repository = "bar" + "#, + ) + .file("level3/src/lib.rs", "") + .build(); + + p.cargo("package -p level2 -p level3 -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(crates_io.index_url()) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level3 v0.0.1 ([ROOT]/foo/level3) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] level3 v0.0.1 ([ROOT]/foo/level3) +[COMPILING] level3 v0.0.1 ([ROOT]/foo/target/package/level3-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2) +[UNPACKING] level3 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] level3 v0.0.1 +[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +// package --list in a workspace lists all the files in all the packages. +// The output is not very good, though. See https://github.com/rust-lang/cargo/issues/13953 +#[cargo_test] +fn workspace_with_local_deps_list() { + let crates_io = registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2"] + "#, + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + level2 = { path = "../level2", version = "0.0.1" } + "#, + ) + .file("level1/src/main.rs", "fn main() {}") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + "#, + ) + .file("level2/src/lib.rs", "") + .build(); + + p.cargo("package --list") + .replace_crates_io(crates_io.index_url()) + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/lib.rs +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn workspace_with_local_deps_index_mismatch() { + let alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + // We're publishing to an alternate index, but the manifests don't specify it. + // The intra-workspace deps won't be found. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2"] + "#, + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + level2 = { path = "../level2", version = "0.0.1" } + "#, + ) + .file("level1/src/main.rs", "fn main() {}") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + "#, + ) + .file("level2/src/lib.rs", "") + .build(); + p.cargo(&format!( + "package --index {} -Zpackage-workspace", + alt_reg.index_url() + )) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] crates.io index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `level2` found + location searched: crates.io index + required by package `level1 v0.0.1 ([ROOT]/foo/level1)` + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_with_local_deps_alternative_index() { + let alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2"] + "#, + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + level2 = { path = "../level2", version = "0.0.1", registry = "alternative" } + "#, + ) + .file("level1/src/main.rs", "fn main() {}") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + "#, + ) + .file("level2/src/lib.rs", "") + .build(); + + p.cargo(&format!( + "package --index {} -Zpackage-workspace", + alt_reg.index_url() + )) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2) +[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] `alternative` index +[UNPACKING] level2 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] level2 v0.0.1 (registry `alternative`) +[COMPILING] level1 v0.0.1 ([ROOT]/foo/target/package/level1-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let index = alt_reg.index_url(); + let generated_lock = format!( + r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "level1" +version = "0.0.1" +dependencies = [ + "level2", +] + +[[package]] +name = "level2" +version = "0.0.1" +source = "{index}" +checksum = "[..]" +"# + ); + + let mut f = File::open(&p.root().join("target/package/level1-0.0.1.crate")).unwrap(); + + validate_crate_contents( + &mut f, + "level1-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [("Cargo.lock", generated_lock)], + ); +} + +fn workspace_with_local_dep_already_published_project() -> Project { + Package::new("dep", "0.1.0").publish(); + + project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + + [dependencies] + dep = { path = "../dep", version = "0.1.0" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + "#, + ) + .file("dep/src/lib.rs", "") + .build() +} + +#[cargo_test] +fn workspace_with_local_dep_already_published() { + let reg = registry::init(); + let p = workspace_with_local_dep_already_published_project(); + + p.cargo("package") + .replace_crates_io(reg.index_url()) + .with_stderr_data( + str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.0 +[COMPILING] dep v0.1.0 +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn workspace_with_local_dep_already_published_nightly() { + let reg = registry::init(); + let p = workspace_with_local_dep_already_published_project(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(reg.index_url()) + .with_stderr_data( + str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] dep v0.1.0 +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn workspace_with_local_and_remote_deps() { + let reg = registry::init(); + + Package::new("dep", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + + [dependencies] + dep = { path = "../dep", version = "0.1.0" } + old_dep = { package = "dep", version = "0.0.1" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(reg.index_url()) + .with_stderr_data( + str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[DOWNLOADING] crates ... +[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`) +[DOWNLOADED] dep v0.0.1 +[COMPILING] dep v0.0.1 +[COMPILING] dep v0.1.0 +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn workspace_with_dot_rs_dir() { + let reg = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["crates/*"] + "#, + ) + .file( + "crates/foo.rs/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.16.2" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + + [dependencies] + "#, + ) + .file("crates/foo.rs/src/lib.rs", "pub fn foo() {}") + .file( + "crates/bar.rs/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.16.2" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + + [dependencies] + foo = { path = "../foo.rs", version = "0.16.2" } + "#, + ) + .file("crates/bar.rs/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(reg.index_url()) + .with_stderr_data( + str![[r#" +[PACKAGING] foo v0.16.2 ([ROOT]/foo/crates/foo.rs) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] bar v0.16.2 ([ROOT]/foo/crates/bar.rs) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.16.2 ([ROOT]/foo/crates/foo.rs) +[COMPILING] foo v0.16.2 ([ROOT]/foo/target/package/foo-0.16.2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] bar v0.16.2 ([ROOT]/foo/crates/bar.rs) +[UNPACKING] foo v0.16.2 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] foo v0.16.2 +[COMPILING] bar v0.16.2 ([ROOT]/foo/target/package/bar-0.16.2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn registry_not_in_publish_list() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + publish = [ + "test" + ] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("package --registry alternative -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `foo` cannot be packaged. +The registry `alternative` is not listed in the `package.publish` value in Cargo.toml. + +"#]]) + .run(); +} + +#[cargo_test] +fn registry_inferred_from_unique_option() { + let _registry = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = ["alternative"] + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = ["alternative"] + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] dep v0.1.0 (registry `alternative`) +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn registry_not_inferred_because_of_conflict() { + let alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = ["alternative"] + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = ["alternative2"] + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] conflicts between `package.publish` fields in the selected packages + +"#]]) + .run(); + + p.cargo("package -Zpackage-workspace --registry=alternative") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `dep` cannot be packaged. +The registry `alternative` is not listed in the `package.publish` value in Cargo.toml. + +"#]]) + .run(); + + p.cargo(&format!( + "package --index {} -Zpackage-workspace", + alt_reg.index_url() + )) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] dep v0.1.0 (registry `alternative`) +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn registry_inference_ignores_unpublishable() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = false + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = ["alternative"] + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] dep v0.1.0 (registry `alternative`) +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("package -Zpackage-workspace --registry=alternative") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[COMPILING] dep v0.1.0 (registry `alternative`) +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn registry_not_inferred_because_of_multiple_options() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = ["alternative", "alternative2"] + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = ["alternative", "alternative2"] + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required to disambiguate between "alternative" or "alternative2" registries + +"#]]) + .run(); + + p.cargo("package -Zpackage-workspace --registry=alternative") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] dep v0.1.0 (registry `alternative`) +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn registry_not_inferred_because_of_mismatch() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = ["alternative"] + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + // No `publish` field means "any registry", but the presence of this package + // will stop us from inferring a registry. + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required because not all `package.publish` settings agree + +"#]]) + .run(); + + p.cargo("package -Zpackage-workspace --registry=alternative") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep) +[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] dep v0.1.0 (registry `alternative`) +[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unpublishable_dependency() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = false + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("package -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[PACKAGING] dep v0.1.0 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[UPDATING] `alternative` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `dep` found + location searched: `alternative` index + required by package `main v0.0.1 ([ROOT]/foo/main)` + +"#]]) + .run(); +} + +#[cargo_test] +fn in_package_workspace_with_members_with_features_old() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [workspace] + members = ["li"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "li/Cargo.toml", + r#" + [package] + name = "li" + version = "0.0.1" + edition = "2015" + rust-version = "1.69" + description = "li" + license = "MIT" + "#, + ) + .file("li/src/main.rs", "fn main() {}") + .build(); + + p.cargo("package -p li --no-verify") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] li v0.0.1 ([ROOT]/foo/li) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(unix)] +fn simple_with_fifo() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + std::process::Command::new("mkfifo") + .current_dir(p.root()) + .arg(p.root().join("blocks-when-read")) + .status() + .expect("a FIFO can be created"); + + // Avoid actual blocking even in case of failure, assuming that what it lists here + // would also be read eventually. + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn git_core_symlinks_false() { + if !symlink_supported() { + return; + } + + let git_project = git::new("bar", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "bar" + description = "bar" + license = "MIT" + edition = "2021" + documentation = "foo" + "#, + ) + .file("src/lib.rs", "//! This is a module") + .symlink("src/lib.rs", "symlink-lib.rs") + .symlink_dir("src", "symlink-dir") + }); + + let url = git_project.root().to_url().to_string(); + + let p = project().build(); + let root = p.root(); + // Remove the default project layout, + // so we can git-fetch from git_project under the same directory + fs::remove_dir_all(&root).unwrap(); + fs::create_dir_all(&root).unwrap(); + let repo = git::init(&root); + + let mut cfg = repo.config().unwrap(); + cfg.set_bool("core.symlinks", false).unwrap(); + + // let's fetch from git_project so it respects our core.symlinks=false config. + repo.remote_anonymous(&url) + .unwrap() + .fetch(&["HEAD"], None, None) + .unwrap(); + let rev = repo + .find_reference("FETCH_HEAD") + .unwrap() + .peel_to_commit() + .unwrap(); + repo.reset(rev.as_object(), git2::ResetType::Hard, None) + .unwrap(); + + p.cargo("package --allow-dirty") + .with_stderr_data(str![[r#" +[WARNING] found symbolic links that may be checked out as regular files for git repo at `[ROOT]/foo/` +This might cause the `.crate` file to include incorrect or incomplete files +[NOTE] to avoid this, set the Git config `core.symlinks` to `true` +... +[PACKAGING] bar v0.0.0 ([ROOT]/foo) +[PACKAGED] 7 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.0.0 ([ROOT]/foo) +[COMPILING] bar v0.0.0 ([ROOT]/foo/target/package/bar-0.0.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/bar-0.0.0.crate")).unwrap(); + validate_crate_contents( + f, + "bar-0.0.0.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/lib.rs", + // We're missing symlink-dir/lib.rs in the `.crate` file. + "symlink-dir", + "symlink-lib.rs", + ".cargo_vcs_info.json", + ], + [ + // And their contents are incorrect. + ("symlink-dir", str!["[ROOT]/bar/src"]), + ("symlink-lib.rs", str!["[ROOT]/bar/src/lib.rs"]), + ], + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package_features.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package_features.rs new file mode 100644 index 000000000..2aeb3903e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/package_features.rs @@ -0,0 +1,994 @@ +//! Tests for feature selection on the command-line. + +use std::fmt::Write; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::{basic_manifest, project, str}; + +use super::features2::switch_to_resolver_2; + +#[cargo_test] +fn virtual_no_default_features() { + // --no-default-features in root of virtual workspace. + Package::new("dep1", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep1 = {version = "1.0", optional = true} + + [features] + default = ["dep1"] + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [features] + default = ["f1"] + f1 = [] + "#, + ) + .file( + "b/src/lib.rs", + r#" + #[cfg(feature = "f1")] + compile_error!{"expected f1 off"} + "#, + ) + .build(); + + p.cargo("check --no-default-features") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[CHECKING] b v0.1.0 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + p.cargo("check --features foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] none of the selected packages contains this feature: foo +selected packages: a, b +[HELP] there is a similarly named feature: f1 + +"#]]) + .run(); + + p.cargo("check --features a/dep1,b/f1,b/f2,f2") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] none of the selected packages contains these features: b/f2, f2 +selected packages: a, b +[HELP] there is a similarly named feature: f1 + +"#]]) + .run(); + + p.cargo("check --features a/dep,b/f1,b/f2,f2") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] none of the selected packages contains these features: a/dep, b/f2, f2 +selected packages: a, b +[HELP] there are similarly named features: a/dep1, f1 + +"#]]) + .run(); + + p.cargo("check --features a/dep,a/dep1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] none of the selected packages contains this feature: a/dep +selected packages: a, b +[HELP] there is a similarly named feature: b/f1 + +"#]]) + .run(); + + p.cargo("check -p b --features=dep1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the package 'b' does not contain this feature: dep1 +[HELP] package with the missing feature: a + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_typo_member_feature() { + project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [features] + deny-warnings = [] + "#, + ) + .file("src/lib.rs", "") + .build() + .cargo("check --features a/deny-warning") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the package 'a' does not contain this feature: a/deny-warning +[HELP] there is a similarly named feature: a/deny-warnings + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_features() { + // --features in root of virtual workspace. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [features] + f1 = [] + "#, + ) + .file( + "a/src/lib.rs", + r#" + #[cfg(not(feature = "f1"))] + compile_error!{"f1 is missing"} + "#, + ) + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check --features f1") + .with_stderr_data( + str![[r#" +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[CHECKING] b v0.1.0 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn virtual_with_specific() { + // -p flags with --features in root of virtual. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [features] + f1 = [] + f2 = [] + "#, + ) + .file( + "a/src/lib.rs", + r#" + #[cfg(not(feature = "f1"))] + compile_error!{"f1 is missing"} + #[cfg(not(feature = "f2"))] + compile_error!{"f2 is missing"} + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [features] + f2 = [] + f3 = [] + "#, + ) + .file( + "b/src/lib.rs", + r#" + #[cfg(not(feature = "f2"))] + compile_error!{"f2 is missing"} + #[cfg(not(feature = "f3"))] + compile_error!{"f3 is missing"} + "#, + ) + .build(); + + p.cargo("check -p a -p b --features f1,f2,f3") + .with_stderr_data( + str![[r#" +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[CHECKING] b v0.1.0 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn other_member_from_current() { + // -p for another member while in the current directory. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path="bar", features=["f3"] } + + [features] + f1 = ["bar/f4"] + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [features] + f1 = [] + f2 = [] + f3 = [] + f4 = [] + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "bar/src/main.rs", + r#" + fn main() { + if cfg!(feature = "f1") { + print!("f1"); + } + if cfg!(feature = "f2") { + print!("f2"); + } + if cfg!(feature = "f3") { + print!("f3"); + } + if cfg!(feature = "f4") { + print!("f4"); + } + println!(); + } + "#, + ) + .build(); + + // Old behavior. + p.cargo("run -p bar --features f1") + .with_stdout_data(str![[r#" +f3f4 + +"#]]) + .run(); + + p.cargo("run -p bar --features f1,f2") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Package `foo v0.1.0 ([ROOT]/foo)` does not have the feature `f2` + +[HELP] a feature with a similar name exists: `f1` + +"#]]) + .run(); + + p.cargo("run -p bar --features bar/f1") + .with_stdout_data(str![[r#" +f1f3 + +"#]]) + .run(); + + // New behavior. + switch_to_resolver_2(&p); + p.cargo("run -p bar --features f1") + .with_stdout_data(str![[r#" +f1 + +"#]]) + .run(); + + p.cargo("run -p bar --features f1,f2") + .with_stdout_data(str![[r#" +f1f2 + +"#]]) + .run(); + + p.cargo("run -p bar --features bar/f1") + .with_stdout_data(str![[r#" +f1 + +"#]]) + .run(); +} + +#[cargo_test] +fn feature_default_resolver() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [features] + test = [] + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(feature = "test") { + println!("feature set"); + } + } + "#, + ) + .build(); + + p.cargo("check --features testt") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Package `a v0.1.0 ([ROOT]/foo)` does not have the feature `testt` + +[HELP] a feature with a similar name exists: `test` + +"#]]) + .run(); + + p.cargo("run --features test") + .with_status(0) + .with_stdout_data(str![[r#" +feature set + +"#]]) + .run(); + + p.cargo("run --features a/test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package `a v0.1.0 ([ROOT]/foo)` does not have a dependency named `a` + +"#]]) + .run(); +} + +#[cargo_test] +fn command_line_optional_dep() { + // Enabling a dependency used as a `dep:` errors helpfully + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [features] + foo = ["dep:bar"] + + [dependencies] + bar = { version = "1.0.0", optional = true } + "#, + ) + .file("src/lib.rs", r#""#) + .build(); + + p.cargo("check --features bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ERROR] Package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`. It has an optional dependency with that name, but that dependency uses the "dep:" syntax in the features table, so it does not have an implicit feature with that name. +Dependency `bar` would be enabled by these features: + - `foo` + +"#]]) + .run(); +} + +#[cargo_test] +fn command_line_optional_dep_three_options() { + // Trying to enable an optional dependency used as a `dep:` errors helpfully, when there are three features which would enable the dependency + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [features] + f1 = ["dep:bar"] + f2 = ["dep:bar"] + f3 = ["dep:bar"] + + [dependencies] + bar = { version = "1.0.0", optional = true } + "#, + ) + .file("src/lib.rs", r#""#) + .build(); + + p.cargo("check --features bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ERROR] Package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`. It has an optional dependency with that name, but that dependency uses the "dep:" syntax in the features table, so it does not have an implicit feature with that name. +Dependency `bar` would be enabled by these features: + - `f1` + - `f2` + - `f3` + +"#]]) + .run(); +} + +#[cargo_test] +fn command_line_optional_dep_many_options() { + // Trying to enable an optional dependency used as a `dep:` errors helpfully, when there are many features which would enable the dependency + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [features] + f1 = ["dep:bar"] + f2 = ["dep:bar"] + f3 = ["dep:bar"] + f4 = ["dep:bar"] + + [dependencies] + bar = { version = "1.0.0", optional = true } + "#, + ) + .file("src/lib.rs", r#""#) + .build(); + + p.cargo("check --features bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ERROR] Package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`. It has an optional dependency with that name, but that dependency uses the "dep:" syntax in the features table, so it does not have an implicit feature with that name. +Dependency `bar` would be enabled by these features: + - `f1` + - `f2` + - `f3` + ... + +"#]]) + .run(); +} + +#[cargo_test] +fn command_line_optional_dep_many_paths() { + // Trying to enable an optional dependency used as a `dep:` errors helpfully, when a features would enable the dependency in multiple ways + Package::new("bar", "1.0.0") + .feature("a", &[]) + .feature("b", &[]) + .feature("c", &[]) + .feature("d", &[]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [features] + f1 = ["dep:bar", "bar/a", "bar/b"] # Remove the implicit feature + f2 = ["bar/b", "bar/c"] # Overlaps with previous + f3 = ["bar/d"] # No overlap with previous + + [dependencies] + bar = { version = "1.0.0", optional = true } + "#, + ) + .file("src/lib.rs", r#""#) + .build(); + + p.cargo("check --features bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ERROR] Package `a v0.1.0 ([ROOT]/foo)` does not have feature `bar`. It has an optional dependency with that name, but that dependency uses the "dep:" syntax in the features table, so it does not have an implicit feature with that name. +Dependency `bar` would be enabled by these features: + - `f1` + - `f2` + - `f3` + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_member_slash() { + // member slash feature syntax + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dependencies] + b = {path="../b", optional=true} + + [features] + default = ["f1"] + f1 = [] + f2 = [] + "#, + ) + .file( + "a/src/lib.rs", + r#" + #[cfg(feature = "f1")] + compile_error!{"f1 is set"} + + #[cfg(feature = "f2")] + compile_error!{"f2 is set"} + + #[cfg(feature = "b")] + compile_error!{"b is set"} + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [features] + bfeat = [] + "#, + ) + .file( + "b/src/lib.rs", + r#" + #[cfg(feature = "bfeat")] + compile_error!{"bfeat is set"} + "#, + ) + .build(); + + p.cargo("check -p a") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] f1 is set +... +"#]]) + .with_stderr_does_not_contain("[..]f2 is set[..]") + .with_stderr_does_not_contain("[..]b is set[..]") + .run(); + + p.cargo("check -p a --features a/f1") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] f1 is set +... +"#]]) + .with_stderr_does_not_contain("[..]f2 is set[..]") + .with_stderr_does_not_contain("[..]b is set[..]") + .run(); + + p.cargo("check -p a --features a/f2") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] f1 is set +... +[ERROR] f2 is set +... +"#]]) + .with_stderr_does_not_contain("[..]b is set[..]") + .run(); + + p.cargo("check -p a --features b/bfeat") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] bfeat is set +... +"#]]) + .run(); + + p.cargo("check -p a --no-default-features").run(); + + p.cargo("check -p a --no-default-features --features b") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] b is set +... +"#]]) + .run(); +} + +#[cargo_test] +fn non_member() { + // -p for a non-member + Package::new("dep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [dependencies] + dep = "1.0" + + [features] + f1 = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -p dep --features f1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify features for packages outside of workspace + +"#]]) + .run(); + + p.cargo("check -p dep --all-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify features for packages outside of workspace + +"#]]) + .run(); + + p.cargo("check -p dep --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify features for packages outside of workspace + +"#]]) + .run(); + + p.cargo("check -p dep") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`) +[CHECKING] dep v1.0.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn resolver1_member_features() { + // --features member-name/feature-name with resolver="1" + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["member1", "member2"] + "#, + ) + .file( + "member1/Cargo.toml", + r#" + [package] + name = "member1" + version = "0.1.0" + edition = "2015" + + [features] + m1-feature = [] + "#, + ) + .file( + "member1/src/main.rs", + r#" + fn main() { + if cfg!(feature = "m1-feature") { + println!("m1-feature set"); + } + } + "#, + ) + .file("member2/Cargo.toml", &basic_manifest("member2", "0.1.0")) + .file("member2/src/lib.rs", "") + .build(); + + p.cargo("run -p member1 --features member1/m1-feature") + .cwd("member2") + .with_stdout_data(str![[r#" +m1-feature set + +"#]]) + .run(); + + p.cargo("check -p member1 --features member1/m2-feature") + .cwd("member2") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Package `member1 v0.1.0 ([ROOT]/foo/member1)` does not have the feature `m2-feature` + +[HELP] a feature with a similar name exists: `m1-feature` + +"#]]) + .run(); +} + +#[cargo_test] +fn non_member_feature() { + // --features for a non-member + Package::new("jazz", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("jazz", "1.0").optional(true)) + .publish(); + let make_toml = |resolver, optional| { + let mut s = String::new(); + write!( + s, + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "{}" + + [dependencies] + "#, + resolver + ) + .unwrap(); + if optional { + s.push_str(r#"bar = { version = "1.0", optional = true } "#); + } else { + s.push_str(r#"bar = "1.0""#) + } + s.push('\n'); + s + }; + let p = project() + .file("Cargo.toml", &make_toml("1", false)) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch").run(); + ///////////////////////// V1 non-optional + eprintln!("V1 non-optional"); + p.cargo("check -p bar") + .with_stderr_data(str![[r#" +[CHECKING] bar v1.0.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // TODO: This should not be allowed (future warning?) + p.cargo("check --features bar/jazz") + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] jazz v1.0.0 (registry `dummy-registry`) +[CHECKING] jazz v1.0.0 +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // TODO: This should not be allowed (future warning?) + p.cargo("check -p bar --features bar/jazz -v") + .with_stderr_data(str![[r#" +[FRESH] jazz v1.0.0 +[FRESH] bar v1.0.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + ///////////////////////// V1 optional + eprintln!("V1 optional"); + p.change_file("Cargo.toml", &make_toml("1", true)); + + // This error isn't great, but is probably unlikely to be common in + // practice, so I'm not going to put much effort into improving it. + p.cargo("check -p bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `bar` did not match any packages + +[HELP] a package with a similar name exists: `foo` + +"#]]) + .run(); + + p.cargo("check -p bar --features bar -v") + .with_stderr_data(str![[r#" +[FRESH] bar v1.0.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // TODO: This should not be allowed (future warning?) + p.cargo("check -p bar --features bar/jazz -v") + .with_stderr_data(str![[r#" +[FRESH] jazz v1.0.0 +[FRESH] bar v1.0.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + ///////////////////////// V2 non-optional + eprintln!("V2 non-optional"); + p.change_file("Cargo.toml", &make_toml("2", false)); + // TODO: This should not be allowed (future warning?) + p.cargo("check --features bar/jazz -v") + .with_stderr_data(str![[r#" +[FRESH] jazz v1.0.0 +[FRESH] bar v1.0.0 +[FRESH] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -p bar -v") + .with_stderr_data(str![[r#" +[FRESH] bar v1.0.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -p bar --features bar/jazz") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify features for packages outside of workspace + +"#]]) + .run(); + + ///////////////////////// V2 optional + eprintln!("V2 optional"); + p.change_file("Cargo.toml", &make_toml("2", true)); + p.cargo("check -p bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `bar` did not match any packages + +[HELP] a package with a similar name exists: `foo` + +"#]]) + .run(); + // New --features behavior does not look at cwd. + p.cargo("check -p bar --features bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify features for packages outside of workspace + +"#]]) + .run(); + p.cargo("check -p bar --features bar/jazz") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify features for packages outside of workspace + +"#]]) + .run(); + p.cargo("check -p bar --features foo/bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify features for packages outside of workspace + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/patch.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/patch.rs new file mode 100644 index 000000000..ff46b3240 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/patch.rs @@ -0,0 +1,3147 @@ +//! Tests for `[patch]` table source replacement. + +use std::fs; + +use cargo_test_support::git; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package}; +use cargo_test_support::{basic_manifest, project, str}; + +#[cargo_test] +fn replace() { + Package::new("bar", "0.1.0").publish(); + Package::new("baz", "0.1.0") + .file( + "src/lib.rs", + "extern crate bar; pub fn baz() { bar::bar(); }", + ) + .dep("bar", "0.1.0") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + baz = "0.1.0" + + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + " + extern crate bar; + extern crate baz; + pub fn bar() { + bar::bar(); + baz::baz(); + } + ", + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] baz v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn from_config() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [patch.crates-io] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn from_config_relative() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + "../.cargo/config.toml", + r#" + [patch.crates-io] + bar = { path = 'foo/bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn from_config_precedence() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = 'no-such-path' } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [patch.crates-io] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn nonexistent() { + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_git() { + let bar = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = {{ git = '{}' }} + + [patch.'{0}'] + bar = {{ path = "bar" }} + "#, + bar.url() + ), + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_to_git() { + 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(); + + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = {{ git = '{}' }} + "#, + bar.url() + ), + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/override` +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn unused() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0")) + .file("bar/src/lib.rs", "not rust code") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] Patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.0 (available: v0.2.0) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] Patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // unused patch should be in the lock file + let lock = p.read_lockfile(); + let toml: toml::Table = toml::from_str(&lock).unwrap(); + assert_eq!(toml["patch"]["unused"].as_array().unwrap().len(), 1); + assert_eq!(toml["patch"]["unused"][0]["name"].as_str(), Some("bar")); + assert_eq!( + toml["patch"]["unused"][0]["version"].as_str(), + Some("0.2.0") + ); +} + +#[cargo_test] +fn unused_with_mismatch_source_being_patched() { + registry::alt_init(); + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.alternative] + bar = { path = "bar" } + + [patch.crates-io] + bar = { path = "baz" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0")) + .file("bar/src/lib.rs", "not rust code") + .file("baz/Cargo.toml", &basic_manifest("bar", "0.3.0")) + .file("baz/src/lib.rs", "not rust code") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] Patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph. +Perhaps you misspelled the source URL being patched. +Possible URLs for `[patch.]`: + crates-io +[WARNING] Patch `bar v0.3.0 ([ROOT]/foo/baz)` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.0 (available: v0.3.0) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn prefer_patch_version() { + Package::new("bar", "0.1.2").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // there should be no patch.unused in the toml file + let lock = p.read_lockfile(); + let toml: toml::Table = toml::from_str(&lock).unwrap(); + assert!(toml.get("patch").is_none()); +} + +#[cargo_test] +fn unused_from_config() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0")) + .file("bar/src/lib.rs", "not rust code") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] Patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.0 (available: v0.2.0) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] Patch `bar v0.2.0 ([ROOT]/foo/bar)` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // unused patch should be in the lock file + let lock = p.read_lockfile(); + let toml: toml::Table = toml::from_str(&lock).unwrap(); + assert_eq!(toml["patch"]["unused"].as_array().unwrap().len(), 1); + assert_eq!(toml["patch"]["unused"][0]["name"].as_str(), Some("bar")); + assert_eq!( + toml["patch"]["unused"][0]["version"].as_str(), + Some("0.2.0") + ); +} + +#[cargo_test] +fn unused_git() { + Package::new("bar", "0.1.0").publish(); + + let foo = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("bar", "0.2.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/override` +[UPDATING] `dummy-registry` index +[WARNING] Patch `bar v0.2.0 ([ROOTURL]/override#[..])` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.0 (available: v0.2.0) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] Patch `bar v0.2.0 ([ROOTURL]/override#[..])` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn add_patch() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = 'bar' } + "#, + ); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn add_patch_from_config() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + ".cargo/config.toml", + r#" + [patch.crates-io] + bar = { path = 'bar' } + "#, + ); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn add_ignored_patch() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = 'bar' } + "#, + ); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] Patch `bar v0.1.1 ([ROOT]/foo/bar)` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] Patch `bar v0.1.1 ([ROOT]/foo/bar)` was not used in the crate graph. +Check that the patched package version and available features are compatible +with the dependency requirements. If the patch has a different version from +what is locked in the Cargo.lock file, run `cargo update` to use the new +version. This may also occur with an optional dependency that is not enabled. +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("update").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn add_patch_with_features() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = 'bar', features = ["some_feature"] } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] patch for `bar` uses the features mechanism. default-features and features will not take effect because the patch dependency does not support this mechanism +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] patch for `bar` uses the features mechanism. default-features and features will not take effect because the patch dependency does not support this mechanism +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn add_patch_with_setting_default_features() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = 'bar', default-features = false, features = ["none_default_feature"] } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] patch for `bar` uses the features mechanism. default-features and features will not take effect because the patch dependency does not support this mechanism +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] patch for `bar` uses the features mechanism. default-features and features will not take effect because the patch dependency does not support this mechanism +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn no_warn_ws_patch() { + Package::new("c", "0.1.0").publish(); + + // Don't issue an unused patch warning when the patch isn't used when + // partially building a workspace. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b", "c"] + + [patch.crates-io] + c = { path = "c" } + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + [dependencies] + c = "0.1.0" + "#, + ) + .file("b/src/lib.rs", "") + .file("c/Cargo.toml", &basic_manifest("c", "0.1.0")) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("check -p a") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn new_minor() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.crates-io] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn transitive_new_minor() { + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = 'bar' } + + [patch.crates-io] + baz = { path = 'baz' } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = '0.1.0' + "#, + ) + .file("bar/src/lib.rs", r#""#) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.1")) + .file("baz/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[CHECKING] baz v0.1.1 ([ROOT]/foo/baz) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn new_major() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.2.0" + + [patch.crates-io] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.2.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + Package::new("bar", "0.2.0").publish(); + p.cargo("update").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.2.0" + "#, + ); + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.2.0 +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.2.0 (registry `dummy-registry`) +[CHECKING] bar v0.2.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn transitive_new_major() { + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = 'bar' } + + [patch.crates-io] + baz = { path = 'baz' } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = '0.2.0' + "#, + ) + .file("bar/src/lib.rs", r#""#) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.2.0")) + .file("baz/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[CHECKING] baz v0.2.0 ([ROOT]/foo/baz) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn shared_by_transitive() { + Package::new("baz", "0.1.1").publish(); + + let baz = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("baz", "0.1.2")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = " 0.1.0" + edition = "2015" + + [dependencies] + bar = {{ path = "bar" }} + baz = "0.1" + + [patch.crates-io] + baz = {{ git = "{}", version = "0.1" }} + "#, + baz.url(), + ), + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + baz = "0.1.1" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/override` +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[CHECKING] baz v0.1.2 ([ROOTURL]/override#[..]) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn remove_patch() { + Package::new("foo", "0.1.0").publish(); + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + + [patch.crates-io] + foo = { path = 'foo' } + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", r#""#) + .build(); + + // Generate a lock file where `foo` is unused + p.cargo("check").run(); + let lock_file1 = p.read_lockfile(); + + // Remove `foo` and generate a new lock file form the old one + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = { path = 'bar' } + "#, + ); + p.cargo("check").run(); + let lock_file2 = p.read_lockfile(); + + // Remove the lock file and build from scratch + fs::remove_file(p.root().join("Cargo.lock")).unwrap(); + p.cargo("check").run(); + let lock_file3 = p.read_lockfile(); + + assert!(lock_file1.contains("foo")); + assert_eq!(lock_file2, lock_file3); + assert_ne!(lock_file1, lock_file2); +} + +#[cargo_test] +fn non_crates_io() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [patch.some-other-source] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + [patch] entry `some-other-source` should be a URL or registry name + +Caused by: + invalid url `some-other-source`: relative URL without a base + +"#]]) + .run(); +} + +#[cargo_test] +fn replace_with_crates_io() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [patch.crates-io] + bar = "0.1" + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index` + +Caused by: + patch for `bar` in `https://github.com/rust-lang/crates.io-index` points to the same source, but patches must point to different sources + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_in_virtual() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", r#""#) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + "#, + ) + .file("foo/src/lib.rs", r#""#) + .build(); + + p.cargo("check -p foo") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check -p foo") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_depends_on_another_patch() { + Package::new("bar", "0.1.0") + .file("src/lib.rs", "broken code") + .publish(); + + Package::new("baz", "0.1.0") + .dep("bar", "0.1") + .file("src/lib.rs", "broken code") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + baz = "0.1" + + [patch.crates-io] + bar = { path = "bar" } + baz = { path = "baz" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + "#, + ) + .file("baz/src/lib.rs", r#""#) + .build(); + + p.cargo("check").run(); + + // Nothing should be rebuilt, no registry should be updated. + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn replace_prerelease() { + Package::new("baz", "1.1.0-pre.1").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + + [patch.crates-io] + baz = { path = "./baz" } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + baz = "1.1.0-pre.1" + "#, + ) + .file( + "bar/src/main.rs", + "extern crate baz; fn main() { baz::baz() }", + ) + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "1.1.0-pre.1" + edition = "2015" + authors = [] + [workspace] + "#, + ) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn patch_older() { + Package::new("baz", "1.0.2").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = 'bar' } + baz = "=1.0.1" + + [patch.crates-io] + baz = { path = "./baz" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + baz = "1.0.0" + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "1.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[CHECKING] baz v1.0.1 ([ROOT]/foo/baz) +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cycle() { + Package::new("a", "1.0.0").publish(); + Package::new("b", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + + [patch.crates-io] + a = {path="a"} + b = {path="b"} + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "1.0.0" + edition = "2015" + + [dependencies] + b = "1.0" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "1.0.0" + edition = "2015" + + [dependencies] + a = "1.0" + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] cyclic package dependency: package `a v1.0.0 ([ROOT]/foo/a)` depends on itself. Cycle: +package `a v1.0.0 ([ROOT]/foo/a)` + ... which satisfies dependency `a = "^1.0"` of package `b v1.0.0 ([ROOT]/foo/b)` + ... which satisfies dependency `b = "^1.0"` of package `a v1.0.0 ([ROOT]/foo/a)` + +"#]]) + .run(); +} + +#[cargo_test] +fn multipatch() { + Package::new("a", "1.0.0").publish(); + Package::new("a", "2.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + a1 = { version = "1", package = "a" } + a2 = { version = "2", package = "a" } + + [patch.crates-io] + b1 = { path = "a1", package = "a" } + b2 = { path = "a2", package = "a" } + "#, + ) + .file("src/lib.rs", "pub fn foo() { a1::f1(); a2::f2(); }") + .file( + "a1/Cargo.toml", + r#" + [package] + name = "a" + version = "1.0.0" + edition = "2015" + "#, + ) + .file("a1/src/lib.rs", "pub fn f1() {}") + .file( + "a2/Cargo.toml", + r#" + [package] + name = "a" + version = "2.0.0" + edition = "2015" + "#, + ) + .file("a2/src/lib.rs", "pub fn f2() {}") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn patch_same_version() { + let bar = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + cargo_test_support::registry::init(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + [dependencies] + bar = "0.1" + [patch.crates-io] + bar = {{ path = "bar" }} + bar2 = {{ git = '{}', package = 'bar' }} + "#, + bar.url(), + ), + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/override` +[ERROR] cannot have two `[patch]` entries which both resolve to `bar v0.1.0` + +"#]]) + .run(); +} + +#[cargo_test] +fn two_semver_compatible() { + let bar = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("src/lib.rs", "") + .build(); + + cargo_test_support::registry::init(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + [dependencies] + bar = "0.1" + [patch.crates-io] + bar = {{ path = "bar" }} + bar2 = {{ git = '{}', package = 'bar' }} + "#, + bar.url(), + ), + ) + .file("src/lib.rs", "pub fn foo() { bar::foo() }") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.2" + edition = "2015" + "#, + ) + .file("bar/src/lib.rs", "pub fn foo() {}") + .build(); + + // assert the build succeeds and doesn't panic anywhere, and then afterwards + // assert that the build succeeds again without updating anything or + // building anything else. + p.cargo("check").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] Patch `bar v0.1.1 ([ROOTURL]/override#[..])` was not used in the crate graph. +Perhaps you misspelled the source URL being patched. +Possible URLs for `[patch.]`: + [ROOT]/foo/bar +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn multipatch_select_big() { + let bar = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + cargo_test_support::registry::init(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + [dependencies] + bar = "*" + [patch.crates-io] + bar = {{ path = "bar" }} + bar2 = {{ git = '{}', package = 'bar' }} + "#, + bar.url(), + ), + ) + .file("src/lib.rs", "pub fn foo() { bar::foo() }") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.2.0" + edition = "2015" + "#, + ) + .file("bar/src/lib.rs", "pub fn foo() {}") + .build(); + + // assert the build succeeds, which is only possible if 0.2.0 is selected + // since 0.1.0 is missing the function we need. Afterwards assert that the + // build succeeds again without updating anything or building anything else. + p.cargo("check").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] Patch `bar v0.1.0 ([ROOTURL]/override#[..])` was not used in the crate graph. +Perhaps you misspelled the source URL being patched. +Possible URLs for `[patch.]`: + [ROOT]/foo/bar +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn canonicalize_a_bunch() { + let base = git::repo(&paths::root().join("base")) + .file("Cargo.toml", &basic_manifest("base", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + let intermediate = git::repo(&paths::root().join("intermediate")) + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "intermediate" + version = "0.1.0" + edition = "2015" + + [dependencies] + # Note the lack of trailing slash + base = {{ git = '{}' }} + "#, + base.url(), + ), + ) + .file("src/lib.rs", "pub fn f() { base::f() }") + .build(); + + let newbase = git::repo(&paths::root().join("newbase")) + .file("Cargo.toml", &basic_manifest("base", "0.1.0")) + .file("src/lib.rs", "pub fn f() {}") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + # Note the trailing slashes + base = {{ git = '{base}/' }} + intermediate = {{ git = '{intermediate}/' }} + + [patch.'{base}'] # Note the lack of trailing slash + base = {{ git = '{newbase}' }} + "#, + base = base.url(), + intermediate = intermediate.url(), + newbase = newbase.url(), + ), + ) + .file("src/lib.rs", "pub fn a() { base::f(); intermediate::f() }") + .build(); + + // Once to make sure it actually works + p.cargo("check").run(); + + // Then a few more times for good measure to ensure no weird warnings about + // `[patch]` are printed. + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn update_unused_new_version() { + // If there is an unused patch entry, and then you update the patch, + // make sure `cargo update` will be able to fix the lock file. + Package::new("bar", "0.1.5").publish(); + + // Start with a lock file to 0.1.5, and an "unused" patch because the + // version is too old. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.1.5" + + [patch.crates-io] + bar = { path = "../bar" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Patch is too old. + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.4")) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] Patch `bar v0.1.4 ([ROOT]/bar)` was not used in the crate graph. +... +"#]]) + .run(); + // unused patch should be in the lock file + let lock = p.read_lockfile(); + let toml: toml::Table = toml::from_str(&lock).unwrap(); + assert_eq!(toml["patch"]["unused"].as_array().unwrap().len(), 1); + assert_eq!(toml["patch"]["unused"][0]["name"].as_str(), Some("bar")); + assert_eq!( + toml["patch"]["unused"][0]["version"].as_str(), + Some("0.1.4") + ); + + // Oh, OK, let's update to the latest version. + bar.change_file("Cargo.toml", &basic_manifest("bar", "0.1.6")); + + // Create a backup so we can test it with different options. + fs::copy(p.root().join("Cargo.lock"), p.root().join("Cargo.lock.bak")).unwrap(); + + // Try to build again, this should automatically update Cargo.lock. + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.6 ([ROOT]/bar) +[CHECKING] bar v0.1.6 ([ROOT]/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // This should not update any registry. + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(!p.read_lockfile().contains("unused")); + + // 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.cargo("update bar") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.6 ([ROOT]/bar) +[REMOVING] bar v0.1.5 + +"#]]) + .run(); + + // Try with bare `cargo update`. + fs::copy(p.root().join("Cargo.lock.bak"), p.root().join("Cargo.lock")).unwrap(); + p.cargo("update") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ADDING] bar v0.1.6 ([ROOT]/bar) +[REMOVING] bar v0.1.5 + +"#]]) + .run(); +} + +#[cargo_test] +fn too_many_matches() { + // The patch locations has multiple versions that match. + registry::alt_init(); + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.0").alternative(true).publish(); + Package::new("bar", "0.1.1").alternative(true).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = { version = "0.1", registry = "alternative" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Picks 0.1.1, the most recent version. + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index` + +Caused by: + patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve + +Caused by: + patch for `bar` in `registry `alternative`` resolved to more than one candidate + Found versions: 0.1.0, 0.1.1 + Update the patch definition to select only one package. + For example, add an `=` version requirement to the patch definition, such as `version = "=0.1.1"`. + +"#]]) + .run(); +} + +#[cargo_test] +fn no_matches() { + // A patch to a location that does not contain the named package. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("abc", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index` + +Caused by: + patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve + +Caused by: + The patch location `[ROOT]/foo/bar` does not appear to contain any packages matching the name `bar`. + +"#]]) + .run(); +} + +#[cargo_test] +fn mismatched_version() { + // A patch to a location that has an old version. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1.1" + + [patch.crates-io] + bar = { path = "bar", version = "0.1.1" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index` + +Caused by: + patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve + +Caused by: + The patch location `[ROOT]/foo/bar` contains a `bar` package with version `0.1.0`, but the patch definition requires `^0.1.1`. + Check that the version in the patch location is what you expect, and update the patch definition to match. + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_walks_backwards() { + // Starting with a locked patch, change the patch so it points to an older version. + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = {path="bar"} + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Somehow the user changes the version backwards. + p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNGRADING] bar v0.1.1 ([ROOT]/foo/bar) -> v0.1.0 +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_walks_backwards_restricted() { + // This is the same as `patch_walks_backwards`, but the patch contains a + // `version` qualifier. This is unusual, just checking a strange edge case. + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = {path="bar", version="0.1.1"} + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Somehow the user changes the version backwards. + p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index` + +Caused by: + patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve + +Caused by: + The patch location `[ROOT]/foo/bar` contains a `bar` package with version `0.1.0`, but the patch definition requires `^0.1.1`. + Check that the version in the patch location is what you expect, and update the patch definition to match. + +"#]]) + .run(); +} + +#[cargo_test] +fn patched_dep_new_version() { + // What happens when a patch is locked, and then one of the patched + // dependencies needs to be updated. In this case, the baz requirement + // gets updated from 0.1.0 to 0.1.1. + Package::new("bar", "0.1.0").dep("baz", "0.1.0").publish(); + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = {path="bar"} + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + baz = "0.1" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + // Lock everything. + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`) +[CHECKING] baz v0.1.0 +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + Package::new("baz", "0.1.1").publish(); + + // Just the presence of the new version should not have changed anything. + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Modify the patch so it requires the new version. + p.change_file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + baz = "0.1.1" + "#, + ); + + // Should unlock and update cleanly. + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] baz v0.1.0 -> v0.1.1 +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.1 (registry `dummy-registry`) +[CHECKING] baz v0.1.1 +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_update_doesnt_update_other_sources() { + // Very extreme edge case, make sure a patch update doesn't update other + // sources. + registry::alt_init(); + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.0").alternative(true).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + bar_alt = { version = "0.1", registry = "alternative", package = "bar" } + + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] `alternative` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `alternative`) +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[CHECKING] bar v0.1.0 (registry `alternative`) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + // Publish new versions in both sources. + Package::new("bar", "0.1.1").publish(); + Package::new("bar", "0.1.1").alternative(true).publish(); + + // Since it is locked, nothing should change. + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Require new version on crates.io. + p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")); + + // This should not update bar_alt. + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.1.0 ([ROOT]/foo/bar) -> v0.1.1 +[CHECKING] bar v0.1.1 ([ROOT]/foo/bar) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn can_update_with_alt_reg() { + // A patch to an alt reg can update. + registry::alt_init(); + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.0").alternative(true).publish(); + Package::new("bar", "0.1.1").alternative(true).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = { version = "=0.1.1", registry = "alternative" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.1 (registry `alternative`) +[CHECKING] bar v0.1.1 (registry `alternative`) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + Package::new("bar", "0.1.2").alternative(true).publish(); + + // Should remain locked. + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // This does nothing, due to `=` requirement. + p.cargo("update bar") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[UPDATING] `dummy-registry` index +[LOCKING] 0 packages to latest compatible versions +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]]) + .run(); + + // Bump to 0.1.2. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + + [patch.crates-io] + bar = { version = "=0.1.2", registry = "alternative" } + "#, + ); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.1.1 (registry `alternative`) -> v0.1.2 +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.2 (registry `alternative`) +[CHECKING] bar v0.1.2 (registry `alternative`) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn gitoxide_clones_shallow_old_git_patch() { + perform_old_git_patch(true) +} + +fn perform_old_git_patch(shallow: bool) { + // Example where an old lockfile with an explicit branch="master" in Cargo.toml. + Package::new("bar", "1.0.0").publish(); + let (bar, bar_repo) = git::new_repo("bar", |p| { + p.file("Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("src/lib.rs", "") + }); + + let bar_oid = bar_repo.head().unwrap().target().unwrap(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + + [patch.crates-io] + bar = {{ git = "{}", branch = "master" }} + "#, + bar.url() + ), + ) + .file( + "Cargo.lock", + &format!( + r#" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bar" +version = "1.0.0" +source = "git+{}#{}" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "bar", +] + "#, + bar.url(), + bar_oid + ), + ) + .file("src/lib.rs", "") + .build(); + + bar.change_file("Cargo.toml", &basic_manifest("bar", "2.0.0")); + git::add(&bar_repo); + git::commit(&bar_repo); + + // This *should* keep the old lock. + let mut cargo = p.cargo("tree"); + if shallow { + cargo + .arg("-Zgitoxide=fetch") + .arg("-Zgit=shallow-deps") + .masquerade_as_nightly_cargo(&[ + "unstable features must be available for -Z gitoxide and -Z git", + ]); + } + cargo + // .env("CARGO_LOG", "trace") + .with_stderr_data( + "\ +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[ADDING] bar v1.0.0 ([ROOTURL]/bar?branch=master#[..]) +", + ) + // .with_status(1) + .with_stdout_data(format!( + "\ +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 ([ROOTURL]/bar?branch=master#{}) +", + &bar_oid.to_string()[..8] + )) + .run(); +} + +#[cargo_test] +fn old_git_patch() { + perform_old_git_patch(false) +} + +// From https://github.com/rust-lang/cargo/issues/7463 +#[cargo_test] +fn patch_eq_conflict_panic() { + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.1").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "=0.1.0" + + [dev-dependencies] + bar = "=0.1.1" + + [patch.crates-io] + bar = {path="bar"} + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for `bar`. + ... required by package `foo v0.1.0 ([ROOT]/foo)` +versions that meet the requirements `=0.1.1` are: 0.1.1 + +all possible versions conflict with previously selected packages. + + previously selected package `bar v0.1.0` + ... which satisfies dependency `bar = "=0.1.0"` of package `foo v0.1.0 ([ROOT]/foo)` + +failed to select a version for `bar` which could resolve this conflict + +"#]]) + .run(); +} + +// From https://github.com/rust-lang/cargo/issues/11336 +#[cargo_test] +fn mismatched_version2() { + Package::new("qux", "0.1.0-beta.1").publish(); + Package::new("qux", "0.1.0-beta.2").publish(); + Package::new("bar", "0.1.0") + .dep("qux", "=0.1.0-beta.1") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1.0" + qux = "0.1.0-beta.2" + + [patch.crates-io] + qux = { path = "qux" } + "#, + ) + .file("src/lib.rs", "") + .file( + "qux/Cargo.toml", + r#" + [package] + name = "qux" + version = "0.1.0-beta.1" + edition = "2015" + "#, + ) + .file("qux/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for `qux`. + ... required by package `bar v0.1.0` + ... which satisfies dependency `bar = "^0.1.0"` of package `foo v0.1.0 ([ROOT]/foo)` +versions that meet the requirements `=0.1.0-beta.1` are: 0.1.0-beta.1 + +all possible versions conflict with previously selected packages. + + previously selected package `qux v0.1.0-beta.2` + ... which satisfies dependency `qux = "^0.1.0-beta.2"` of package `foo v0.1.0 ([ROOT]/foo)` + +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" + edition = "2015" + + [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_data(str![[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 ([ROOT]/foo)` +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(); +} + +#[cargo_test] +fn from_config_empty() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [patch.''] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] [patch] entry `` should be a URL or registry name + +Caused by: + invalid url ``: relative URL without a base + +"#]]) + .run(); +} + +#[cargo_test] +fn from_manifest_empty() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [patch.''] + bar = { path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1")) + .file("bar/src/lib.rs", r#""#) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + [patch] entry `` should be a URL or registry name + +Caused by: + invalid url ``: relative URL without a base + +"#]]) + .run(); +} + +#[cargo_test] +fn patched_reexport_stays_locked() { + // Patch example where you emulate a semver-incompatible patch via a re-export. + // Testing an issue where the lockfile does not stay locked after a new version is published. + Package::new("bar", "1.0.0").publish(); + Package::new("bar", "2.0.0").publish(); + Package::new("bar", "3.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + + + [package] + name = "foo" + + [dependencies] + bar1 = {package="bar", version="1.0.0"} + bar2 = {package="bar", version="2.0.0"} + + [patch.crates-io] + bar1 = { package = "bar", path = "bar-1-as-3" } + bar2 = { package = "bar", path = "bar-2-as-3" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar-1-as-3/Cargo.toml", + r#" + [package] + name = "bar" + version = "1.0.999" + + [dependencies] + bar = "3.0.0" + "#, + ) + .file("bar-1-as-3/src/lib.rs", "") + .file( + "bar-2-as-3/Cargo.toml", + r#" + [package] + name = "bar" + version = "2.0.999" + + [dependencies] + bar = "3.0.0" + "#, + ) + .file("bar-2-as-3/src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.0 ([ROOT]/foo) +├── bar v1.0.999 ([ROOT]/foo/bar-1-as-3) +│ └── bar v3.0.0 +└── bar v2.0.999 ([ROOT]/foo/bar-2-as-3) + └── bar v3.0.0 + +"#]]) + .run(); + + std::fs::copy( + p.root().join("Cargo.lock"), + p.root().join("Cargo.lock.orig"), + ) + .unwrap(); + + Package::new("bar", "3.0.1").publish(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.0 ([ROOT]/foo) +├── bar v1.0.999 ([ROOT]/foo/bar-1-as-3) +│ └── bar v3.0.0 +└── bar v2.0.999 ([ROOT]/foo/bar-2-as-3) + └── bar v3.0.0 + +"#]]) + .run(); + + assert_eq!(p.read_file("Cargo.lock"), p.read_file("Cargo.lock.orig")); +} + +#[cargo_test] +fn patch_in_real_with_base() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "pub fn hello() {}") + .build(); + Package::new("bar", "0.5.0").publish(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + test = '{}' + "#, + bar.root().parent().unwrap().display() + ), + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + edition = "2018" + + [dependencies] + bar = "0.5.0" + + [patch.crates-io] + bar = { base = 'test', path = 'bar' } + "#, + ) + .file("src/lib.rs", "use bar::hello as _;") + .build(); + + p.cargo("tree") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_stdout_data(str![[r#" +foo v0.5.0 ([ROOT]/foo) +└── bar v0.5.0 ([ROOT]/bar) + +"#]]) + .run(); +} + +#[cargo_test] +fn patch_in_virtual_with_base() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "pub fn hello() {}") + .build(); + Package::new("bar", "0.5.0").publish(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + test = '{}' + "#, + bar.root().parent().unwrap().display() + ), + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [workspace] + members = ["foo"] + + [patch.crates-io] + bar = { base = 'test', path = 'bar' } + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + edition = "2018" + + [dependencies] + bar = "0.5.0" + "#, + ) + .file("foo/src/lib.rs", "use bar::hello as _;") + .build(); + + p.cargo("tree") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_stdout_data(str![[r#" +foo v0.5.0 ([ROOT]/foo/foo) +└── bar v0.5.0 ([ROOT]/bar) + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/path.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/path.rs new file mode 100644 index 000000000..131f4fa98 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/path.rs @@ -0,0 +1,1922 @@ +//! Tests for `path` dependencies. + +use std::fs; + +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_lib_manifest, basic_manifest, main_file, project}; +use cargo_test_support::{sleep_ms, t}; + +#[cargo_test] +// I have no idea why this is failing spuriously on Windows; +// for more info, see #3466. +#[cfg(not(windows))] +fn cargo_compile_with_nested_deps_shorthand() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + + version = "0.5.0" + path = "bar" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.baz] + + version = "0.5.0" + path = "baz" + + [lib] + + name = "bar" + "#, + ) + .file( + "bar/src/bar.rs", + r#" + extern crate baz; + + pub fn gimme() -> String { + baz::gimme() + } + "#, + ) + .file("bar/baz/Cargo.toml", &basic_lib_manifest("baz")) + .file( + "bar/baz/src/baz.rs", + r#" + pub fn gimme() -> String { + "test passed".to_string() + } + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] baz v0.5.0 ([ROOT]/foo/bar/baz) +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +test passed + +"#]]) + .run(); + + println!("cleaning"); + p.cargo("clean -v") + .with_stderr_data(str![[r#" +[REMOVING] [ROOT]/foo/target +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + println!("building baz"); + p.cargo("build -p baz") + .with_stderr_data(str![[r#" +[COMPILING] baz v0.5.0 ([ROOT]/foo/bar/baz) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + println!("building foo"); + p.cargo("build -p foo") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_root_dev_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dev-dependencies.bar] + + version = "0.5.0" + path = "../bar" + + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .build(); + let _p2 = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file( + "src/lib.rs", + r#" + pub fn gimme() -> &'static str { + "zoidberg" + } + "#, + ) + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] foo v0.5.0 ([ROOT]/foo) +error[E0463]: can't find crate for `bar` +... +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_root_dev_deps_with_testing() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dev-dependencies.bar] + + version = "0.5.0" + path = "../bar" + + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .build(); + let _p2 = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file( + "src/lib.rs", + r#" + pub fn gimme() -> &'static str { + "zoidberg" + } + "#, + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_compile_with_transitive_dev_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + + version = "0.5.0" + path = "bar" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dev-dependencies.baz] + + git = "git://example.com/path/to/nowhere" + + [lib] + + name = "bar" + "#, + ) + .file( + "bar/src/bar.rs", + r#" + pub fn gimme() -> &'static str { + "zoidberg" + } + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +zoidberg + +"#]]) + .run(); +} + +#[cargo_test] +fn no_rebuild_dependency() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::bar() }") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/bar.rs", "pub fn bar() {}") + .build(); + // First time around we should compile both foo and bar + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + sleep_ms(1000); + p.change_file( + "src/main.rs", + r#" + extern crate bar; + fn main() { bar::bar(); } + "#, + ); + // Don't compile bar, but do recompile foo. + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn deep_dependencies_trigger_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::bar() }") + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + name = "bar" + [dependencies.baz] + path = "../baz" + "#, + ) + .file( + "bar/src/bar.rs", + "extern crate baz; pub fn bar() { baz::baz() }", + ) + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file("baz/src/baz.rs", "pub fn baz() {}") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] baz v0.5.0 ([ROOT]/foo/baz) +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Make sure an update to baz triggers a rebuild of bar + // + // We base recompilation off mtime, so sleep for at least a second to ensure + // that this write will change the mtime. + sleep_ms(1000); + p.change_file("baz/src/baz.rs", r#"pub fn baz() { println!("hello!"); }"#); + sleep_ms(1000); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] baz v0.5.0 ([ROOT]/foo/baz) +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Make sure an update to bar doesn't trigger baz + sleep_ms(1000); + p.change_file( + "bar/src/bar.rs", + r#" + extern crate baz; + pub fn bar() { println!("hello!"); baz::baz(); } + "#, + ); + sleep_ms(1000); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn no_rebuild_two_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = "bar" + [dependencies.baz] + path = "baz" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::bar() }") + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [lib] + name = "bar" + [dependencies.baz] + path = "../baz" + "#, + ) + .file("bar/src/bar.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_lib_manifest("baz")) + .file("baz/src/baz.rs", "pub fn baz() {}") + .build(); + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] baz v0.5.0 ([ROOT]/foo/baz) +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.bin("foo").is_file()); + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn nested_deps_recompile() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + + version = "0.5.0" + path = "src/bar" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file("src/bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("src/bar/src/bar.rs", "pub fn gimme() -> i32 { 92 }") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.5.0 ([ROOT]/foo/src/bar) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + sleep_ms(1000); + + p.change_file("src/main.rs", r#"fn main() {}"#); + + // This shouldn't recompile `bar` + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn error_message_for_missing_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + + path = "src/bar" + "#, + ) + .file("src/lib.rs", "") + .file("src/bar/not-a-manifest", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `bar` as a dependency of package `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update [ROOT]/foo/src/bar + +Caused by: + failed to read `[ROOT]/foo/src/bar/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn path_bases_not_stable() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + test = '{}' + "#, + bar.root().parent().unwrap().display() + ), + ) + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { base = 'test', path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data( + "\ +[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml` + +Caused by: + resolving path dependency bar + +Caused by: + feature `path-bases` is required + + The package requires the Cargo feature called `path-bases`, but that feature is not stabilized in this version of Cargo ([..]). + Consider trying a newer version of Cargo (this may require the nightly release). + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#path-bases for more information about the status of this feature. +", + ) + .run(); +} + +#[cargo_test] +fn path_with_base() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + test = '{}' + "#, + bar.root().parent().unwrap().display() + ), + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { base = 'test', path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["path-bases"]) + .run(); +} + +#[cargo_test] +fn current_dir_with_base() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + test = '{}' + "#, + bar.root().display() + ), + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { base = 'test', path = '.' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["path-bases"]) + .run(); +} + +#[cargo_test] +fn parent_dir_with_base() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + test = '{}/subdir' + "#, + bar.root().display() + ), + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { base = 'test', path = '..' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["path-bases"]) + .run(); +} + +#[cargo_test] +fn inherit_dependency_using_base() { + let bar = project() + .at("dep_with_base") + .file("Cargo.toml", &basic_manifest("dep_with_base", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + test = '{}' + "#, + bar.root().parent().unwrap().display() + ), + ) + .file( + "Cargo.toml", + r#" + [package] + name = "parent" + version = "0.1.0" + authors = [] + + [workspace] + members = ["child"] + + [workspace.dependencies] + dep_with_base = { base = 'test', path = 'dep_with_base' } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "child/Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "child" + version = "0.1.0" + authors = [] + + [dependencies] + dep_with_base = { workspace = true } + "#, + ) + .file("child/src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["path-bases"]) + .run(); +} + +#[cargo_test] +fn path_with_relative_base() { + project() + .at("shared_proj/bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "../.cargo/config.toml", + r#" + [path-bases] + test = 'shared_proj' + "#, + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { base = 'test', path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["path-bases"]) + .run(); +} + +#[cargo_test] +fn workspace_builtin_base() { + project() + .at("dep_with_base") + .file("Cargo.toml", &basic_manifest("dep_with_base", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "parent" + version = "0.1.0" + authors = [] + + [workspace] + members = ["child"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "child/Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "child" + version = "0.1.0" + authors = [] + + [dependencies] + dep_with_base = { base = 'workspace', path = '../dep_with_base' } + "#, + ) + .file("child/src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["path-bases"]) + .run(); +} + +#[cargo_test] +fn workspace_builtin_base_not_a_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + bar = { base = 'workspace', path = 'bar' } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_status(101) + .with_stderr_data( + "\ +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + resolving path dependency bar + +Caused by: + failed to find a workspace root +", + ) + .run(); +} + +#[cargo_test] +fn shadow_workspace_builtin_base() { + let bar = project() + .at("dep_with_base") + .file("Cargo.toml", &basic_manifest("dep_with_base", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [path-bases] + workspace = '{}/subdir/anotherdir' + "#, + bar.root().parent().unwrap().display() + ), + ) + .file( + "Cargo.toml", + r#" + [package] + name = "parent" + version = "0.1.0" + authors = [] + + [workspace] + members = ["child"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "child/Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "child" + version = "0.1.0" + authors = [] + + [dependencies] + dep_with_base = { base = 'workspace', path = '../../dep_with_base' } + "#, + ) + .file("child/src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["path-bases"]) + .run(); +} + +#[cargo_test] +fn unknown_base() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { base = 'test', path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_status(101) + .with_stderr_data( + "\ +[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml` + +Caused by: + resolving path dependency bar + +Caused by: + path base `test` is undefined. You must add an entry for `test` in the Cargo configuration [path-bases] table. +", + ) + .run(); +} + +#[cargo_test] +fn base_without_path() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { version = '1.0.0', base = 'test' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_status(101) + .with_stderr_data( + "\ +[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml` + +Caused by: + resolving path dependency bar + +Caused by: + `base` can only be used with path dependencies +", + ) + .run(); +} + +#[cargo_test] +fn invalid_base() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + + [dependencies] + bar = { base = '^^not-valid^^', path = 'bar' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_status(101) + .with_stderr_data( + "\ +[ERROR] invalid character `^` in path base name: `^^not-valid^^`, the first character must be a Unicode XID start character (most letters or `_`) + + + --> Cargo.toml:10:23 + | +10 | bar = { base = '^^not-valid^^', path = 'bar' } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +", + ) + .run(); +} + +#[cargo_test] +fn invalid_path_with_base() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [path-bases] + test = 'shared_proj' + "#, + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + edition = "2015" + + [dependencies] + bar = { base = 'test', path = '"' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_status(101) + .with_stderr_data( + "\ +[ERROR] failed to get `bar` as a dependency of package `foo v0.5.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update [ROOT]/foo/shared_proj/\" + +Caused by: + failed to read `[ROOT]/foo/shared_proj/\"/Cargo.toml` + +Caused by: + [NOT_FOUND] +", + ) + .run(); +} + +#[cargo_test] +fn self_dependency_using_base() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [path-bases] + test = '.' + "#, + ) + .file( + "Cargo.toml", + r#" + cargo-features = ["path-bases"] + + [package] + name = "foo" + version = "0.1.0" + authors = [] + edition = "2015" + + [dependencies] + foo = { base = 'test', path = '.' } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build") + .masquerade_as_nightly_cargo(&["path-bases"]) + .with_status(101) + .with_stderr_data( + "\ +[ERROR] cyclic package dependency: package `foo v0.1.0 ([ROOT]/foo)` depends on itself. Cycle: +package `foo v0.1.0 ([ROOT]/foo)` + ... which satisfies path dependency `foo` of package `foo v0.1.0 ([ROOT]/foo)` +", + ) + .run(); +} + +#[cargo_test] +fn override_relative() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + fs::create_dir(&paths::root().join(".cargo")).unwrap(); + fs::write( + &paths::root().join(".cargo/config.toml"), + r#"paths = ["bar"]"#, + ) + .unwrap(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = '{}' + "#, + bar.root().display() + ), + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check -v").run(); +} + +#[cargo_test] +fn override_self() { + let bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("src/lib.rs", "") + .build(); + + let p = project(); + let root = p.root(); + let p = p + .file( + ".cargo/config.toml", + &format!("paths = ['{}']", root.display()), + ) + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + path = '{}' + + "#, + bar.root().display() + ), + ) + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn override_path_dep() { + let bar = project() + .at("bar") + .file( + "p1/Cargo.toml", + r#" + [package] + name = "p1" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies.p2] + path = "../p2" + "#, + ) + .file("p1/src/lib.rs", "") + .file("p2/Cargo.toml", &basic_manifest("p2", "0.5.0")) + .file("p2/src/lib.rs", "") + .build(); + + let p = project() + .file( + ".cargo/config.toml", + &format!( + "paths = ['{}', '{}']", + bar.root().join("p1").display(), + bar.root().join("p2").display() + ), + ) + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.p2] + path = '{}' + + "#, + bar.root().join("p2").display() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v").run(); +} + +#[cargo_test] +fn path_dep_build_cmd() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + + [dependencies.bar] + + version = "0.5.0" + path = "bar" + "#, + ) + .file("src/main.rs", &main_file(r#""{}", bar::gimme()"#, &["bar"])) + .file( + "bar/Cargo.toml", + r#" + [package] + + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["wycats@example.com"] + build = "build.rs" + + [lib] + name = "bar" + path = "src/bar.rs" + "#, + ) + .file( + "bar/build.rs", + r#" + use std::fs; + fn main() { + fs::copy("src/bar.rs.in", "src/bar.rs").unwrap(); + } + "#, + ) + .file("bar/src/bar.rs.in", "pub fn gimme() -> i32 { 0 }") + .build(); + p.root().join("bar").move_into_the_past(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +0 + +"#]]) + .run(); + + // Touching bar.rs.in should cause the `build` command to run again. + p.change_file("bar/src/bar.rs.in", "pub fn gimme() -> i32 { 1 }"); + + p.cargo("build") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +1 + +"#]]) + .run(); +} + +#[cargo_test] +fn dev_deps_no_rebuild_lib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dev-dependencies.bar] + path = "bar" + + [lib] + name = "foo" + doctest = false + "#, + ) + .file( + "src/lib.rs", + r#" + #[cfg(test)] #[allow(unused_extern_crates)] extern crate bar; + #[cfg(not(test))] pub fn foo() { env!("FOO"); } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.5.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + p.cargo("build") + .env("FOO", "bar") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_target_no_rebuild() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + a = { path = "a" } + [workspace] + members = ["a", "b"] + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.5.0")) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + a = { path = "../a" } + "#, + ) + .file("b/src/lib.rs", "") + .build(); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] a v0.5.0 ([ROOT]/foo/a) +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + t!(fs::rename( + p.root().join("target"), + p.root().join("target_moved") + )); + p.cargo("check --manifest-path=b/Cargo.toml") + .env("CARGO_TARGET_DIR", "target_moved") + .with_stderr_data(str![[r#" +[CHECKING] b v0.5.0 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn override_and_depend() { + let p = project() + .no_manifest() + .file( + "a/a1/Cargo.toml", + r#" + [package] + name = "a1" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + a2 = { path = "../a2" } + "#, + ) + .file("a/a1/src/lib.rs", "") + .file("a/a2/Cargo.toml", &basic_manifest("a2", "0.5.0")) + .file("a/a2/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.5.0" + edition = "2015" + authors = [] + [dependencies] + a1 = { path = "../a/a1" } + a2 = { path = "../a/a2" } + "#, + ) + .file("b/src/lib.rs", "") + .file("b/.cargo/config.toml", r#"paths = ["../a"]"#) + .build(); + p.cargo("check") + .cwd("b") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[CHECKING] a2 v0.5.0 ([ROOT]/foo/a) +[CHECKING] a1 v0.5.0 ([ROOT]/foo/a) +[CHECKING] b v0.5.0 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn missing_path_dependency() { + let p = project() + .file("Cargo.toml", &basic_manifest("a", "0.5.0")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#"paths = ["../whoa-this-does-not-exist"]"#, + ) + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to update path override `[ROOT]/whoa-this-does-not-exist` (defined in `[ROOT]/foo/.cargo/config.toml`) + +Caused by: + failed to read directory `[ROOT]/whoa-this-does-not-exist` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_path_dep_in_workspace_with_lockfile() { + Package::new("bar", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "top" + version = "0.5.0" + edition = "2015" + authors = [] + + [workspace] + + [dependencies] + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + // Generate a lock file + p.cargo("check").run(); + + // Change the dependency on `bar` to an invalid path + p.change_file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "" } + "#, + ); + + // Make sure we get a nice error. In the past this actually stack + // overflowed! + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no matching package found +searched package name: `bar` +perhaps you meant: foo +location searched: [ROOT]/foo/foo +required by package `foo v0.5.0 ([ROOT]/foo/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_produces_rlib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "top" + version = "0.5.0" + edition = "2015" + authors = [] + + [workspace] + + [dependencies] + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.5.0")) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + assert!(p.root().join("target/debug/libtop.rlib").is_file()); + assert!(!p.root().join("target/debug/libfoo.rlib").is_file()); +} + +#[cargo_test] +fn deep_path_error() { + // Test for an error loading a path deep in the dependency graph. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + a = {path="a"} + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + [dependencies] + b = {path="../b"} + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + [dependencies] + c = {path="../c"} + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `c` as a dependency of package `b v0.1.0 ([ROOT]/foo/b)` + ... which satisfies path dependency `b` of package `a v0.1.0 ([ROOT]/foo/a)` + ... which satisfies path dependency `a` of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `c` + +Caused by: + Unable to update [ROOT]/foo/c + +Caused by: + failed to read `[ROOT]/foo/c/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn catch_tricky_cycle() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "message" + version = "0.1.0" + edition = "2015" + + [dev-dependencies] + test = { path = "test" } + "#, + ) + .file("src/lib.rs", "") + .file( + "tangle/Cargo.toml", + r#" + [package] + name = "tangle" + version = "0.1.0" + edition = "2015" + + [dependencies] + message = { path = ".." } + snapshot = { path = "../snapshot" } + "#, + ) + .file("tangle/src/lib.rs", "") + .file( + "snapshot/Cargo.toml", + r#" + [package] + name = "snapshot" + version = "0.1.0" + edition = "2015" + + [dependencies] + ledger = { path = "../ledger" } + "#, + ) + .file("snapshot/src/lib.rs", "") + .file( + "ledger/Cargo.toml", + r#" + [package] + name = "ledger" + version = "0.1.0" + edition = "2015" + + [dependencies] + tangle = { path = "../tangle" } + "#, + ) + .file("ledger/src/lib.rs", "") + .file( + "test/Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + + [dependencies] + snapshot = { path = "../snapshot" } + "#, + ) + .file("test/src/lib.rs", "") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[ERROR] cyclic package dependency: package `ledger v0.1.0 ([ROOT]/foo/ledger)` depends on itself. Cycle: +package `ledger v0.1.0 ([ROOT]/foo/ledger)` +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn same_name_version_changed() { + // Illustrates having two path packages with the same name, but different versions. + // Verifies it works correctly when one of the versions is changed. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + edition = "2021" + + [dependencies] + foo2 = { path = "foo2", package = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo2/Cargo.toml", + r#" + [package] + name = "foo" + version = "2.0.0" + edition = "2021" + "#, + ) + .file("foo2/src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version + +"#]]) + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +└── foo v2.0.0 ([ROOT]/foo/foo2) + +"#]]) + .run(); + + p.change_file( + "foo2/Cargo.toml", + r#" + [package] + name = "foo" + version = "2.0.1" + edition = "2021" + "#, + ); + p.cargo("tree") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ADDING] foo v2.0.1 ([ROOT]/foo/foo2) + +"#]]) + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +└── foo v2.0.1 ([ROOT]/foo/foo2) + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/paths.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/paths.rs new file mode 100644 index 000000000..8df1263f6 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/paths.rs @@ -0,0 +1,252 @@ +//! Tests for `paths` overrides. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, project}; + +#[cargo_test] +fn broken_path_override_warns() { + 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.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a1" } + "#, + ) + .file("src/lib.rs", "") + .file( + "a1/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + "#, + ) + .file("a1/src/lib.rs", "") + .file( + "a2/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.2" + "#, + ) + .file("a2/src/lib.rs", "") + .file(".cargo/config.toml", r#"paths = ["a2"]"#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[WARNING] path override for crate `a` has altered the original list of +dependencies; the dependency on `bar` was either added or +modified to not match the previously resolved version + +This is currently allowed but is known to produce buggy behavior with spurious +recompiles and changes to the crate graph. Path overrides unfortunately were +never intended to support this feature, so for now this message is just a +warning. In the future, however, this message will become a hard error. + +To change the dependency graph via an override it's recommended to use the +`[patch]` feature of Cargo instead of the path override feature. This is +documented online at the url below for more information. + +https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html + +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.2.0 (registry `dummy-registry`) +[CHECKING] bar v0.2.0 +[CHECKING] a v0.0.1 ([ROOT]/foo/a2) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn override_to_path_dep() { + Package::new("bar", "0.1.0").dep("baz", "0.1").publish(); + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + authors = [] + + [dependencies] + baz = { path = "baz" } + "#, + ) + .file("bar/src/lib.rs", "") + .file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.0.1")) + .file("bar/baz/src/lib.rs", "") + .file(".cargo/config.toml", r#"paths = ["bar"]"#) + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn paths_ok_with_optional() { + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { version = "0.1", optional = true } + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "bar2/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { version = "0.1", optional = true } + "#, + ) + .file("bar2/src/lib.rs", "") + .file(".cargo/config.toml", r#"paths = ["bar2"]"#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar2) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn paths_add_optional_bad() { + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + authors = [] + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .file( + "bar2/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2021" + authors = [] + + [dependencies] + baz = { version = "0.1", optional = true } + "#, + ) + .file("bar2/src/lib.rs", "") + .file(".cargo/config.toml", r#"paths = ["bar2"]"#) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[WARNING] path override for crate `bar` has altered the original list of +dependencies; the dependency on `baz` was either added or +modified to not match the previously resolved version + +This is currently allowed but is known to produce buggy behavior with spurious +recompiles and changes to the crate graph. Path overrides unfortunately were +never intended to support this feature, so for now this message is just a +warning. In the future, however, this message will become a hard error. + +To change the dependency graph via an override it's recommended to use the +`[patch]` feature of Cargo instead of the path override feature. This is +documented online at the url below for more information. + +https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html + +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar2) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pgo.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pgo.rs new file mode 100644 index 000000000..8676e73f5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pgo.rs @@ -0,0 +1,112 @@ +//! Test if PGO works. + +use std::path::PathBuf; +use std::process::Command; + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +fn llvm_profdata() -> Option { + let output = Command::new("rustc") + .arg("--print=target-libdir") + .output() + .expect("rustc to run"); + assert!(output.status.success()); + let mut libdir = PathBuf::from(String::from_utf8(output.stdout).unwrap()); + assert!(libdir.pop()); + let mut bin = libdir.join("bin").join("llvm-profdata"); + bin.exists().then(|| bin.clone()).or_else(|| { + bin.set_extension("exe"); + bin.exists().then_some(bin) + }) +} + +// Rustc build may be without profiling support. +// Mark it as nightly so it won't run on rust-lang/rust CI. +#[cfg_attr( + target_os = "linux", + cargo_test(nightly, reason = "rust-lang/rust#133675") +)] +// macOS may emit different LLVM PGO warnings. +// Windows LLVM has different requirements. +#[cfg_attr(not(target_os = "linux"), cargo_test, ignore = "linux only")] +fn pgo_works() { + let Some(llvm_profdata) = llvm_profdata() else { + return; + }; + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2021" + "#, + ) + .file( + "src/main.rs", + r#" + fn fibonacci(n: u64) -> u64 { + match n { + 0 => 0, + 1 => 1, + _ => fibonacci(n - 1) + fibonacci(n - 2), + } + } + + fn main() { + for i in [15, 20, 25] { + let _ = fibonacci(i); + } + } + "#, + ) + .build(); + + let target_dir = p.build_dir(); + let release_bin = target_dir.join("release").join("foo"); + let pgo_data_dir = target_dir.join("pgo-data"); + let profdata_path = target_dir.join("merged.profdata"); + + // Build the instrumented binary + p.cargo("build --release") + .env( + "RUSTFLAGS", + format!("-Cprofile-generate={}", pgo_data_dir.display()), + ) + .run(); + // Run the instrumented binary + cargo_test_support::execs() + .with_process_builder(cargo_test_support::process(release_bin)) + .run(); + + cargo_test_support::process(llvm_profdata) + .arg("merge") + .arg("-o") + .arg(&profdata_path) + .arg(pgo_data_dir) + .status() + .unwrap(); + + // Use merged profdata during optimization. + // + // -Cllvm-args=-pgo-warn-missing-function is essential. + // If there are LLVM warnings, there might be something wrong. + p.cargo("build --release -v") + .env( + "RUSTFLAGS", + format!( + "-Cprofile-use={} -Cllvm-args=-pgo-warn-missing-function", + profdata_path.display() + ), + ) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-Cprofile-use=[ROOT]/foo/target/merged.profdata -Cllvm-args=-pgo-warn-missing-function` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pkgid.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pkgid.rs new file mode 100644 index 000000000..9e51c59c7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pkgid.rs @@ -0,0 +1,407 @@ +//! Tests for the `cargo pkgid` command. + +use cargo_test_support::basic_lib_manifest; +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::git; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +#[cargo_test] +fn local() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + "#, + ) + .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(); + + p.cargo("pkgid foo") + .with_stdout_data(str![[r#" +path+[ROOTURL]/foo#0.1.0 + +"#]]) + .run(); + + // Bad file URL. + p.cargo("pkgid ./Cargo.toml") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid package ID specification: `./Cargo.toml` + +Caused by: + package ID specification `./Cargo.toml` looks like a file path, maybe try [ROOTURL]/foo/Cargo.toml + +"#]]) + .run(); + + // Bad file URL with similar name. + p.cargo("pkgid './bar'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid package ID specification: `./bar` + +[HELP] a package with a similar name exists: `bar` + +Caused by: + package ID specification `./bar` looks like a file path, maybe try [ROOTURL]/foo/bar + +"#]]) + .run(); +} + +#[cargo_test] +fn registry() { + Package::new("crates-io", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + crates-io = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("cratesio", "") + .build(); + + p.cargo("generate-lockfile").run(); + + p.cargo("pkgid crates-io") + .with_stdout_data(str![[r#" +registry+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) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `https://example.com/crates-io` did not match any packages +[HELP] there are similar package ID specifications: + + crates-io@0.1.0 + +"#]]) + .run(); + + // Bad name. + p.cargo("pkgid crates_io") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `crates_io` did not match any packages + +[HELP] a package with a similar name exists: `crates-io` + +"#]]) + .run(); +} + +#[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_data(str![[r#" +registry+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_data(str![[r#" +[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(); + + // Incomplete version. + p.cargo("pkgid two-ver@0.2") + .with_stdout_data(str![[r#" +registry+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_data(str![[r#" +[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 version. + p.cargo("pkgid two-ver:0.3.0") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `two-ver@0.3.0` did not match any packages +[HELP] there are similar package ID specifications: + + two-ver@0.1.0 + two-ver@0.2.0 + +"#]]) + .run(); +} + +// Not for `cargo pkgid` but the `PackageIdSpec` format +#[cargo_test] +fn multiple_git_same_version() { + // Test what happens if different packages refer to the same git repo with + // different refs, and the package version is the same. + let (xyz_project, xyz_repo) = git::new_repo("xyz", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("xyz")) + .file("src/lib.rs", "fn example() {}") + }); + let rev1 = xyz_repo.revparse_single("HEAD").unwrap().id(); + xyz_project.change_file("src/lib.rs", "pub fn example() {}"); + git::add(&xyz_repo); + let rev2 = git::commit(&xyz_repo); + // Both rev1 and rev2 point to version 0.1.0. + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = {{ path = "bar" }} + xyz = {{ git = "{}", rev = "{}" }} + + "#, + xyz_project.url(), + rev1 + ), + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + &format!( + r#" + [package] + name = "bar" + version = "0.1.0" + + [dependencies] + xyz = {{ git = "{}", rev = "{}" }} + "#, + xyz_project.url(), + rev2 + ), + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + p.cargo("tree") + .with_stdout_data(&format!( + "\ +foo v0.1.0 ([ROOT]/foo) +├── bar v0.1.0 ([ROOT]/foo/bar) +│ └── xyz v0.5.0 ([ROOTURL]/xyz?rev={}#{}) +└── xyz v0.5.0 ([ROOTURL]/xyz?rev={}#{}) +", + rev2, + &rev2.to_string()[..8], + rev1, + &rev1.to_string()[..8] + )) + .run(); + // FIXME: This fails since xyz is ambiguous, but the + // possible pkgids are also ambiguous. + p.cargo("pkgid xyz") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] There are multiple `xyz` packages in your project, and the specification `xyz` is ambiguous. +Please re-run this command with one of the following specifications: + git+[ROOTURL]/xyz?rev=[..]#0.5.0 + git+[ROOTURL]/xyz?rev=[..]#0.5.0 + +"#]]) + .run(); + // TODO, what should the `-p` value be here? + //p.cargo("update -p") +} + +// Keep Package ID format in sync among +// +// * Package ID specifications +// * machine-readable message via `--message-format=json` +// * `cargo metadata` output +#[cargo_test] +fn pkgid_json_message_metadata_consistency() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "fn unused() {}") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile").run(); + + let output = p.cargo("pkgid").arg("foo").run(); + let pkgid = String::from_utf8(output.stdout).unwrap(); + let pkgid = pkgid.trim(); + assert_e2e().eq(pkgid, str!["path+[ROOTURL]/foo#0.5.0"]); + + p.cargo("check --message-format=json") + .with_stdout_data( + str![[r#" +[ + { + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-artifact", + "...": "{...}" + }, + { + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "build-script-executed", + "...": "{...}" + }, + { + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-message", + "...": "{...}" + }, + { + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.5.0", + "reason": "compiler-artifact", + "...": "{...}" + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); + + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [ + "wycats@example.com" + ], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#0.5.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "foo", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": "{...}", + "version": "0.5.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo#0.5.0" + } + ], + "root": "path+[ROOTURL]/foo#0.5.0" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#0.5.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/precise_pre_release.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/precise_pre_release.rs new file mode 100644 index 000000000..71c9a3a78 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/precise_pre_release.rs @@ -0,0 +1,189 @@ +//! Tests for selecting pre-release versions with `update --precise`. + +use cargo_test_support::prelude::*; +use cargo_test_support::{project, str}; + +#[cargo_test] +fn requires_nightly_cargo() { + cargo_test_support::registry::init(); + + for version in ["0.1.1", "0.1.2-pre.0"] { + cargo_test_support::registry::Package::new("my-dependency", version).publish(); + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "package" + [dependencies] + my-dependency = "0.1.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update my-dependency --precise 0.1.2-pre.0") + .with_status(101) + // This error is suffering from #12579 but still demonstrates that updating to + // a pre-release does not work on stable + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `my-dependency = "^0.1.1"` +candidate versions found which didn't match: 0.1.2-pre.0 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `package v0.0.0 ([ROOT]/foo)` +if you are looking for the prerelease package it needs to be specified explicitly + my-dependency = { version = "0.1.2-pre.0" } +perhaps a crate was updated and forgotten to be re-vendored? + +"#]]) + .run(); +} + +#[cargo_test] +fn update_pre_release() { + cargo_test_support::registry::init(); + + for version in ["0.1.1", "0.1.2-pre.0"] { + cargo_test_support::registry::Package::new("my-dependency", version).publish(); + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "package" + [dependencies] + my-dependency = "0.1.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update my-dependency --precise 0.1.2-pre.0 -Zunstable-options") + .masquerade_as_nightly_cargo(&["precise-pre-release"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] my-dependency v0.1.1 -> v0.1.2-pre.0 + +"#]]) + .run(); + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.2-pre.0\"")); +} + +#[cargo_test] +fn pre_release_should_unmatched() { + cargo_test_support::registry::init(); + + cargo_test_support::registry::Package::new("my-dependency", "0.1.2").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "package" + [dependencies] + my-dependency = "0.1.2" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("generate-lockfile").run(); + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.2\"")); + + // 0.1.2-pre.0 < 0.1.2 so it doesn't match + cargo_test_support::registry::Package::new("my-dependency", "0.1.2-pre.0").publish(); + p.cargo("update -p my-dependency --precise 0.1.2-pre.0 -Zunstable-options") + .masquerade_as_nightly_cargo(&["precise-pre-release"]) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `my-dependency = "^0.1.2"` +candidate versions found which didn't match: 0.1.2-pre.0 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `package v0.0.0 ([ROOT]/foo)` +if you are looking for the prerelease package it needs to be specified explicitly + my-dependency = { version = "0.1.2-pre.0" } +perhaps a crate was updated and forgotten to be re-vendored? + +"#]]) + .run(); + + cargo_test_support::registry::Package::new("my-dependency", "0.2.0-0").publish(); + // 0.2.0-0 is the upper bound we exclude, so it doesn't match + p.cargo("update -p my-dependency --precise 0.2.0-0 -Zunstable-options") + .masquerade_as_nightly_cargo(&["precise-pre-release"]) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `my-dependency = "^0.1.2"` +candidate versions found which didn't match: 0.2.0-0 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `package v0.0.0 ([ROOT]/foo)` +if you are looking for the prerelease package it needs to be specified explicitly + my-dependency = { version = "0.2.0-0" } +perhaps a crate was updated and forgotten to be re-vendored? + +"#]]) + .run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.2\"")); +} + +#[cargo_test] +fn pre_release_should_matched() { + cargo_test_support::registry::init(); + + cargo_test_support::registry::Package::new("my-dependency", "0.1.2").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "package" + [dependencies] + my-dependency = "0.1.2" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("generate-lockfile").run(); + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.2\"")); + + // Test upgrade + // 0.1.3 is in the range, so it match + cargo_test_support::registry::Package::new("my-dependency", "0.1.3").publish(); + p.cargo("update -p my-dependency --precise 0.1.3 -Zunstable-options") + .masquerade_as_nightly_cargo(&["precise-pre-release"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] my-dependency v0.1.2 -> v0.1.3 + +"#]]) + .run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.3\"")); + + // Test downgrade + // v0.1.3-pre.1 is in the range, so it match + cargo_test_support::registry::Package::new("my-dependency", "0.1.3-pre.1").publish(); + p.cargo("update -p my-dependency --precise 0.1.3-pre.1 -Zunstable-options") + .masquerade_as_nightly_cargo(&["precise-pre-release"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNGRADING] my-dependency v0.1.3 -> v0.1.3-pre.1 + +"#]]) + .run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"my-dependency\"\nversion = \"0.1.3-pre.1\"")); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/proc_macro.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/proc_macro.rs new file mode 100644 index 000000000..73dd121b9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/proc_macro.rs @@ -0,0 +1,570 @@ +//! Tests for proc-macros. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn probe_cfg_before_crate_type_discovery() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(not(stage300))'.dependencies.noop] + path = "../noop" + "#, + ) + .file( + "src/main.rs", + r#" + #[macro_use] + extern crate noop; + + #[derive(Noop)] + struct X; + + fn main() {} + "#, + ) + .build(); + let _noop = project() + .at("noop") + .file( + "Cargo.toml", + r#" + [package] + name = "noop" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Noop)] + pub fn noop(_input: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn noop() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.noop] + path = "../noop" + "#, + ) + .file( + "src/main.rs", + r#" + #[macro_use] + extern crate noop; + + #[derive(Noop)] + struct X; + + fn main() {} + "#, + ) + .build(); + let _noop = project() + .at("noop") + .file( + "Cargo.toml", + r#" + [package] + name = "noop" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Noop)] + pub fn noop(_input: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .build(); + + p.cargo("check").run(); + p.cargo("check").run(); +} + +#[cargo_test] +fn impl_and_derive() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.transmogrify] + path = "../transmogrify" + "#, + ) + .file( + "src/main.rs", + r#" + #[macro_use] + extern crate transmogrify; + + trait ImplByTransmogrify { + fn impl_by_transmogrify(&self) -> bool; + } + + #[derive(Transmogrify, Debug)] + struct X { success: bool } + + fn main() { + let x = X::new(); + assert!(x.impl_by_transmogrify()); + println!("{:?}", x); + } + "#, + ) + .build(); + let _transmogrify = project() + .at("transmogrify") + .file( + "Cargo.toml", + r#" + [package] + name = "transmogrify" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Transmogrify)] + #[doc(hidden)] + pub fn transmogrify(input: TokenStream) -> TokenStream { + " + impl X { + fn new() -> Self { + X { success: true } + } + } + + impl ImplByTransmogrify for X { + fn impl_by_transmogrify(&self) -> bool { + true + } + } + ".parse().unwrap() + } + "#, + ) + .build(); + + p.cargo("build").run(); + p.cargo("run") + .with_stdout_data(str![[r#" +X { success: true } + +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro_doctest() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + #![crate_type = "proc-macro"] + + extern crate proc_macro; + + use proc_macro::TokenStream; + + /// ``` + /// assert!(true); + /// ``` + #[proc_macro_derive(Bar)] + pub fn derive(_input: TokenStream) -> TokenStream { + "".parse().unwrap() + } + + #[test] + fn a() { + assert!(true); + } + "#, + ) + .build(); + + foo.cargo("test") + .with_stdout_data(str![[r#" + +running 1 test +test a ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test src/lib.rs - derive (line 8) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro_crate_type() { + // Verify that `crate-type = ["proc-macro"]` is the same as `proc-macro = true` + // and that everything, including rustdoc, works correctly. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [dependencies] + pm = { path = "pm" } + "#, + ) + .file( + "src/lib.rs", + r#" + //! ``` + //! use foo::THING; + //! assert_eq!(THING, 123); + //! ``` + #[macro_use] + extern crate pm; + #[derive(MkItem)] + pub struct S; + #[cfg(test)] + mod tests { + use super::THING; + #[test] + fn it_works() { + assert_eq!(THING, 123); + } + } + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + [lib] + crate-type = ["proc-macro"] + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(MkItem)] + pub fn mk_item(_input: TokenStream) -> TokenStream { + "pub const THING: i32 = 123;".parse().unwrap() + } + "#, + ) + .build(); + + foo.cargo("test") + .with_stdout_data(str![[r#" + +running 1 test +test tests::it_works ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test src/lib.rs - (line 2) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro_crate_type_warning() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + crate-type = ["proc-macro"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] library `foo` should only specify `proc-macro = true` instead of setting `crate-type` +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn lib_plugin_unused_key_warning() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + plugin = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] unused manifest key: lib.plugin +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro_crate_type_warning_plugin() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + crate-type = ["proc-macro"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] library `foo` should only specify `proc-macro = true` instead of setting `crate-type` +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro_crate_type_multiple() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [lib] + crate-type = ["proc-macro", "rlib"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + foo.cargo("check") + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + cannot mix `proc-macro` crate type with others + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn proc_macro_extern_prelude() { + // Check that proc_macro is in the extern prelude. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + [lib] + proc-macro = true + "#, + ) + .file( + "src/lib.rs", + r#" + use proc_macro::TokenStream; + #[proc_macro] + pub fn foo(input: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .build(); + p.cargo("test").run(); + p.cargo("doc").run(); +} + +#[cargo_test] +fn proc_macro_built_once() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ['a', 'b'] + resolver = "2" + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [build-dependencies] + the-macro = { path = '../the-macro' } + "#, + ) + .file("a/build.rs", "fn main() {}") + .file("a/src/main.rs", "fn main() {}") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + + [dependencies] + the-macro = { path = '../the-macro', features = ['a'] } + "#, + ) + .file("b/src/main.rs", "fn main() {}") + .file( + "the-macro/Cargo.toml", + r#" + [package] + name = "the-macro" + version = "0.1.0" + edition = "2015" + + [lib] + proc-macro = true + + [features] + a = [] + "#, + ) + .file("the-macro/src/lib.rs", "") + .build(); + p.cargo("build --verbose") + .with_stderr_data( + str![[r#" +[COMPILING] the-macro v0.1.0 ([ROOT]/foo/the-macro) +[RUNNING] `rustc --crate-name the_macro [..]` +[COMPILING] b v0.1.0 ([ROOT]/foo/b) +[RUNNING] `rustc --crate-name b [..]` +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name build_script_build [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/a-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name a [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_config.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_config.rs new file mode 100644 index 000000000..e3afa09f0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_config.rs @@ -0,0 +1,526 @@ +//! Tests for profiles defined in config files. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_lib_manifest, paths, project, str}; +use cargo_util_schemas::manifest::TomlDebugInfo; + +// TODO: this should be remove once -Zprofile-rustflags is stabilized +#[cargo_test] +fn rustflags_works_with_zflag() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [profile.dev] + rustflags = ["-C", "link-dead-code=yes"] + "#, + ) + .build(); + + p.cargo("check -v") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] config profile `dev` is not valid (defined in `[ROOT]/foo/.cargo/config.toml`) + +Caused by: + feature `profile-rustflags` is required +... +"#]]) + .run(); + + p.cargo("check -v -Zprofile-rustflags") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.change_file( + ".cargo/config.toml", + r#" + [unstable] + profile-rustflags = true + + [profile.dev] + rustflags = ["-C", "link-dead-code=yes"] + "#, + ); + + p.cargo("check -v") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_stderr_data(str![[r#" +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_config_validate_warnings() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [profile.test] + opt-level = 3 + + [profile.asdf] + opt-level = 3 + + [profile.dev] + bad-key = true + + [profile.dev.build-override] + bad-key-bo = true + + [profile.dev.package.bar] + bad-key-bar = true + "#, + ) + .build(); + + p.cargo("build").with_stderr_data(str![[r#" +[WARNING] unused config key `profile.dev.bad-key` in `[ROOT]/foo/.cargo/config.toml` +[WARNING] unused config key `profile.dev.build-override.bad-key-bo` in `[ROOT]/foo/.cargo/config.toml` +[WARNING] unused config key `profile.dev.package.bar.bad-key-bar` in `[ROOT]/foo/.cargo/config.toml` +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()).run(); +} + +#[cargo_test] +fn profile_config_error_paths() { + // Errors in config show where the error is located. + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [profile.dev] + opt-level = 3 + "#, + ) + .file( + paths::home().join(".cargo/config.toml"), + r#" + [profile.dev] + rpath = "foo" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `profile.dev` + +Caused by: + error in [ROOT]/home/.cargo/config.toml: `profile.dev.rpath` expected true/false, but found a string + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_config_validate_errors() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [profile.dev.package.foo] + panic = "abort" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] config profile `dev` is not valid (defined in `[ROOT]/foo/.cargo/config.toml`) + +Caused by: + `panic` may not be specified in a `package` profile + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_config_syntax_errors() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [profile.dev] + codegen-units = "foo" + "#, + ) + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `profile.dev` + +Caused by: + error in [ROOT]/foo/.cargo/config.toml: `profile.dev.codegen-units` expected an integer, but found a string + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_config_override_spec_multiple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [profile.dev.package.bar] + opt-level = 3 + + [profile.dev.package."bar:0.5.0"] + opt-level = 3 + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + // Unfortunately this doesn't tell you which file, hopefully it's not too + // much of a problem. + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] multiple package overrides in profile `dev` match package `bar v0.5.0 ([ROOT]/foo/bar)` +found package specs: bar, bar@0.5.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_config_all_options() { + // Ensure all profile options are supported. + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [profile.release] + opt-level = 1 + debug = true + debug-assertions = true + overflow-checks = false + rpath = true + lto = true + codegen-units = 2 + panic = "abort" + incremental = true + "#, + ) + .build(); + + p.cargo("build --release -v") + .env_remove("CARGO_INCREMENTAL") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C opt-level=1 -C panic=abort -C lto[..]-C codegen-units=2 -C debuginfo=2 [..]-C debug-assertions=on -C overflow-checks=off [..]-C rpath --out-dir [ROOT]/foo/target/release/deps -C incremental=[ROOT]/foo/target/release/incremental[..]` +[FINISHED] `release` profile [optimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_config_override_precedence() { + // Config values take precedence over manifest values. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = {path = "bar"} + + [profile.dev] + codegen-units = 2 + + [profile.dev.package.bar] + opt-level = 3 + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [profile.dev.package.bar] + opt-level = 2 + "#, + ) + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..] -C opt-level=2[..]-C codegen-units=2 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]-C codegen-units=2 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_config_no_warn_unknown_override() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [profile.dev.package.bar] + codegen-units = 4 + "#, + ) + .build(); + + p.cargo("build") + .with_stderr_does_not_contain("[..]warning[..]") + .run(); +} + +#[cargo_test] +fn profile_config_mixed_types() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [profile.dev] + opt-level = 3 + "#, + ) + .file( + paths::home().join(".cargo/config.toml"), + r#" + [profile.dev] + opt-level = 's' + "#, + ) + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C opt-level=3 [..]` +[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn named_config_profile() { + // Exercises config named profiles. + // foo -> middle -> bar -> dev + // middle exists in Cargo.toml, the others in .cargo/config.toml + use super::config::GlobalContextBuilder; + use cargo::core::compiler::CompileKind; + use cargo::core::profiles::{Profiles, UnitFor}; + use cargo::core::{PackageId, Workspace}; + use cargo::util::interning::InternedString; + use std::fs; + paths::root().join(".cargo").mkdir_p(); + fs::write( + paths::root().join(".cargo/config.toml"), + r#" + [profile.foo] + inherits = "middle" + codegen-units = 2 + [profile.foo.build-override] + codegen-units = 6 + [profile.foo.package.dep] + codegen-units = 7 + + [profile.middle] + inherits = "bar" + codegen-units = 3 + + [profile.bar] + inherits = "dev" + codegen-units = 4 + debug = 1 + "#, + ) + .unwrap(); + fs::write( + paths::root().join("Cargo.toml"), + r#" + [workspace] + + [profile.middle] + inherits = "bar" + codegen-units = 1 + opt-level = 1 + [profile.middle.package.dep] + overflow-checks = false + + [profile.foo.build-override] + codegen-units = 5 + debug-assertions = false + [profile.foo.package.dep] + codegen-units = 8 + "#, + ) + .unwrap(); + let gctx = GlobalContextBuilder::new().build(); + let profile_name = InternedString::new("foo"); + let ws = Workspace::new(&paths::root().join("Cargo.toml"), &gctx).unwrap(); + let profiles = Profiles::new(&ws, profile_name).unwrap(); + + let crates_io = cargo::core::SourceId::crates_io(&gctx).unwrap(); + let a_pkg = PackageId::try_new("a", "0.1.0", crates_io).unwrap(); + let dep_pkg = PackageId::try_new("dep", "0.1.0", crates_io).unwrap(); + + // normal package + let kind = CompileKind::Host; + let p = profiles.get_profile(a_pkg, true, true, UnitFor::new_normal(kind), kind); + assert_eq!(p.name, "foo"); + assert_eq!(p.codegen_units, Some(2)); // "foo" from config + assert_eq!(p.opt_level, "1"); // "middle" from manifest + assert_eq!(p.debuginfo.into_inner(), TomlDebugInfo::Limited); // "bar" from config + assert_eq!(p.debug_assertions, true); // "dev" built-in (ignore build-override) + assert_eq!(p.overflow_checks, true); // "dev" built-in (ignore package override) + + // build-override + let bo = profiles.get_profile(a_pkg, true, true, UnitFor::new_host(false, kind), kind); + assert_eq!(bo.name, "foo"); + assert_eq!(bo.codegen_units, Some(6)); // "foo" build override from config + assert_eq!(bo.opt_level, "0"); // default to zero + assert_eq!(bo.debuginfo.into_inner(), TomlDebugInfo::Limited); // SAME as normal + assert_eq!(bo.debug_assertions, false); // "foo" build override from manifest + assert_eq!(bo.overflow_checks, true); // SAME as normal + + // package overrides + let po = profiles.get_profile(dep_pkg, false, true, UnitFor::new_normal(kind), kind); + assert_eq!(po.name, "foo"); + assert_eq!(po.codegen_units, Some(7)); // "foo" package override from config + assert_eq!(po.opt_level, "1"); // SAME as normal + assert_eq!(po.debuginfo.into_inner(), TomlDebugInfo::Limited); // SAME as normal + assert_eq!(po.debug_assertions, true); // SAME as normal + assert_eq!(po.overflow_checks, false); // "middle" package override from manifest +} + +#[cargo_test] +fn named_env_profile() { + // Environment variables used to define a named profile. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v --profile=other") + .env("CARGO_PROFILE_OTHER_CODEGEN_UNITS", "1") + .env("CARGO_PROFILE_OTHER_INHERITS", "dev") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C codegen-units=1 [..]` +[FINISHED] `other` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn test_with_dev_profile() { + // The `test` profile inherits from `dev` for both local crates and + // dependencies. + Package::new("somedep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + somedep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("test --lib --no-run -v") + .env("CARGO_PROFILE_DEV_DEBUG", "0") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] somedep v1.0.0 (registry `dummy-registry`) +[COMPILING] somedep v1.0.0 +[RUNNING] `rustc --crate-name somedep [..]` +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `test` profile [unoptimized] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .with_stdout_does_not_contain("[..] -C debuginfo=0[..]") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_custom.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_custom.rs new file mode 100644 index 000000000..393f6bb04 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_custom.rs @@ -0,0 +1,701 @@ +//! Tests for named profiles. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_lib_manifest, project, str}; + +#[cargo_test] +fn inherits_on_release() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.release] + inherits = "dev" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `inherits` must not be specified in root profile `release` + +"#]]) + .run(); +} + +#[cargo_test] +fn missing_inherits() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.release-lto] + codegen-units = 7 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] profile `release-lto` is missing an `inherits` directive (`inherits` is required for all profiles except `dev` or `release`) + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_profile_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.'.release-lto'] + inherits = "release" + codegen-units = 7 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid character `.` in profile name: `.release-lto`, allowed characters are letters, numbers, underscore, and hyphen + --> Cargo.toml:8:26 + | +8 | [profile.'.release-lto'] + | ^^^^^^^^^^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +// We are currently uncertain if dir-name will ever be exposed to the user. +// The code for it still roughly exists, but only for the internal profiles. +// This test was kept in case we ever want to enable support for it again. +#[ignore = "dir-name is disabled"] +fn invalid_dir_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.'release-lto'] + inherits = "release" + dir-name = ".subdir" + codegen-units = 7 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + Invalid character `.` in dir-name: `.subdir`", + +"#]]) + .run(); +} + +#[cargo_test] +fn dir_name_disabled() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.release-lto] + inherits = "release" + dir-name = "lto" + lto = true + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + dir-name="lto" in profile `release-lto` is not currently allowed, directory names are tied to the profile name for custom profiles + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_inherits() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.'release-lto'] + inherits = ".release" + codegen-units = 7 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] profile `release-lto` inherits from `.release`, but that profile is not defined + +"#]]) + .run(); +} + +#[cargo_test] +fn non_existent_inherits() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.release-lto] + codegen-units = 7 + inherits = "non-existent" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] profile `release-lto` inherits from `non-existent`, but that profile is not defined + +"#]]) + .run(); +} + +#[cargo_test] +fn self_inherits() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.release-lto] + codegen-units = 7 + inherits = "release-lto" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] profile inheritance loop detected with profile `release-lto` inheriting `release-lto` + +"#]]) + .run(); +} + +#[cargo_test] +fn inherits_loop() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.release-lto] + codegen-units = 7 + inherits = "release-lto2" + + [profile.release-lto2] + codegen-units = 7 + inherits = "release-lto" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] profile inheritance loop detected with profile `release-lto2` inheriting `release-lto` + +"#]]) + .run(); +} + +#[cargo_test] +fn overrides_with_custom() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + xxx = {path = "xxx"} + yyy = {path = "yyy"} + + [profile.dev] + codegen-units = 7 + + [profile.dev.package.xxx] + codegen-units = 5 + [profile.dev.package.yyy] + codegen-units = 3 + + [profile.other] + inherits = "dev" + codegen-units = 2 + + [profile.other.package.yyy] + codegen-units = 6 + "#, + ) + .file("src/lib.rs", "") + .file("xxx/Cargo.toml", &basic_lib_manifest("xxx")) + .file("xxx/src/lib.rs", "") + .file("yyy/Cargo.toml", &basic_lib_manifest("yyy")) + .file("yyy/src/lib.rs", "") + .build(); + + // profile overrides are inherited between profiles using inherits and have a + // higher priority than profile options provided by custom profiles + p.cargo("build -v") + .with_stderr_data( + str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] xxx v0.5.0 ([ROOT]/foo/xxx) +[COMPILING] yyy v0.5.0 ([ROOT]/foo/yyy) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]` +[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=3 [..]` +[RUNNING] `rustc --crate-name foo [..] -C codegen-units=7 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + // This also verifies that the custom profile names appears in the finished line. + p.cargo("build --profile=other -v") + .with_stderr_data( + str![[r#" +[COMPILING] xxx v0.5.0 ([ROOT]/foo/xxx) +[COMPILING] yyy v0.5.0 ([ROOT]/foo/yyy) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name xxx [..] -C codegen-units=5 [..]` +[RUNNING] `rustc --crate-name yyy [..] -C codegen-units=6 [..]` +[RUNNING] `rustc --crate-name foo [..] -C codegen-units=2 [..]` +[FINISHED] `other` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn conflicting_usage() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --profile=dev --release") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--profile ' cannot be used with '--release' + +Usage: cargo[EXE] build --profile + +For more information, try '--help'. + +"#]]) + .run(); + + p.cargo("install --profile=release --debug") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--profile ' cannot be used with '--debug' + +Usage: cargo[EXE] install --profile [CRATE[@]]... + +For more information, try '--help'. + +"#]]) + .run(); + + p.cargo("check --profile=dev --release") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--profile ' cannot be used with '--release' + +Usage: cargo[EXE] check --profile + +For more information, try '--help'. + +"#]]) + .run(); +} + +#[cargo_test] +fn clean_custom_dirname() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.other] + inherits = "release" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("clean -p foo").run(); + + p.cargo("build --release") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("clean -p foo --release").run(); + + p.cargo("build --release") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build --profile=other") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `other` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("clean").arg("--release").run(); + + // Make sure that 'other' was not cleaned + assert!(p.build_dir().is_dir()); + assert!(p.build_dir().join("debug").is_dir()); + assert!(p.build_dir().join("other").is_dir()); + assert!(!p.build_dir().join("release").is_dir()); + + // This should clean 'other' + p.cargo("clean --profile=other") + .with_stderr_data(str![[r#" +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); + assert!(p.build_dir().join("debug").is_dir()); + assert!(!p.build_dir().join("other").is_dir()); +} + +#[cargo_test] +fn unknown_profile() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --profile alpha") + .with_stderr_data(str![[r#" +[ERROR] profile `alpha` is not defined + +"#]]) + .with_status(101) + .run(); + // Clean has a separate code path, need to check it too. + p.cargo("clean --profile alpha") + .with_stderr_data(str![[r#" +[ERROR] profile `alpha` is not defined + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn reserved_profile_names() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.doc] + opt-level = 1 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --profile=doc") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] profile `doc` is reserved and not allowed to be explicitly specified + +"#]]) + .run(); + // Not an exhaustive list, just a sample. + for name in ["build", "cargo", "check", "rustc", "CaRgO_startswith"] { + p.cargo(&format!("build --profile={}", name)) + .with_status(101) + .with_stderr_data(&format!( + "\ +[ERROR] profile name `{}` is reserved +Please choose a different name. +See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles. +", + name + )) + .run(); + } + for name in ["build", "check", "cargo", "rustc", "CaRgO_startswith"] { + p.change_file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.{}] + opt-level = 1 + "#, + name + ), + ); + + let highlight = "^".repeat(name.len()); + p.cargo("build") + .with_status(101) + .with_stderr_data(&format!( + "\ +[ERROR] profile name `{name}` is reserved +Please choose a different name. +See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles. + --> Cargo.toml:7:30 + | +7 | [profile.{name}] + | {highlight} + | +" + )) + .run(); + } + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [profile.debug] + debug = 1 + inherits = "dev" + "#, + ); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] profile name `debug` is reserved +To configure the default development profile, use the name `dev` as in [profile.dev] +See https://doc.rust-lang.org/cargo/reference/profiles.html for more on configuring profiles. + --> Cargo.toml:8:25 + | +8 | [profile.debug] + | ^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn legacy_commands_support_custom() { + // These commands have had `--profile` before custom named profiles. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.super-dev] + codegen-units = 3 + inherits = "dev" + "#, + ) + .file("src/lib.rs", "") + .build(); + + for command in ["rustc", "fix", "check"] { + let mut pb = p.cargo(command); + if command == "fix" { + pb.arg("--allow-no-vcs"); + } + pb.arg("--profile=super-dev") + .arg("-v") + .with_stderr_data(str![ + r#" +... +[RUNNING] [..]codegen-units=3[..] +... +"# + ]) + .run(); + p.build_dir().rm_rf(); + } +} + +#[cargo_test] +fn legacy_rustc() { + // `cargo rustc` historically has supported dev/test/bench/check + // other profiles are covered in check::rustc_check + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.dev] + codegen-units = 3 + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("rustc --profile dev -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]-C codegen-units=3[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_overrides.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_overrides.rs new file mode 100644 index 000000000..d0bc44bc3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_overrides.rs @@ -0,0 +1,611 @@ +//! Tests for profile overrides (build-override and per-package overrides). + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_lib_manifest, basic_manifest, project, str}; + +#[cargo_test] +fn profile_override_basic() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = {path = "bar"} + + [profile.dev] + opt-level = 1 + + [profile.dev.package.bar] + opt-level = 3 + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar [..] -C opt-level=3 [..]` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C opt-level=1 [..]` +[FINISHED] `dev` profile [optimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_override_warnings() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = {path = "bar"} + + [profile.dev.package.bart] + opt-level = 3 + + [profile.dev.package.no-suggestion] + opt-level = 3 + + [profile.dev.package."bar:1.2.3"] + opt-level = 3 + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build").with_stderr_data(str![[r#" +... +[WARNING] profile package spec `bar@1.2.3` in profile `dev` has a version or URL that does not match any of the packages: bar v0.5.0 ([ROOT]/foo/bar) +[WARNING] profile package spec `bart` in profile `dev` did not match any packages + +[HELP] a package with a similar name exists: `bar` +[WARNING] profile package spec `no-suggestion` in profile `dev` did not match any packages +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn profile_override_bad_settings() { + let bad_values = [ + ( + "panic = \"abort\"", + "`panic` may not be specified in a `package` profile", + ), + ( + "lto = true", + "`lto` may not be specified in a `package` profile", + ), + ( + "rpath = true", + "`rpath` may not be specified in a `package` profile", + ), + ("package = {}", "package-specific profiles cannot be nested"), + ]; + for &(snippet, expected) in bad_values.iter() { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = {{path = "bar"}} + + [profile.dev.package.bar] + {} + "#, + snippet + ), + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(format!( + "\ +... +Caused by:\n {} +", + expected + )) + .run(); + } +} + +#[cargo_test] +fn profile_override_hierarchy() { + // Test that the precedence rules are correct for different types. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["m1", "m2", "m3"] + + [profile.dev] + codegen-units = 1 + + [profile.dev.package.m2] + codegen-units = 2 + + [profile.dev.package."*"] + codegen-units = 3 + + [profile.dev.build-override] + codegen-units = 4 + "#, + ) + // m1 + .file( + "m1/Cargo.toml", + r#" + [package] + name = "m1" + version = "0.0.1" + edition = "2015" + + [dependencies] + m2 = { path = "../m2" } + dep = { path = "../../dep" } + "#, + ) + .file("m1/src/lib.rs", "extern crate m2; extern crate dep;") + .file("m1/build.rs", "fn main() {}") + // m2 + .file( + "m2/Cargo.toml", + r#" + [package] + name = "m2" + version = "0.0.1" + edition = "2015" + + [dependencies] + m3 = { path = "../m3" } + + [build-dependencies] + m3 = { path = "../m3" } + dep = { path = "../../dep" } + "#, + ) + .file("m2/src/lib.rs", "extern crate m3;") + .file( + "m2/build.rs", + "extern crate m3; extern crate dep; fn main() {}", + ) + // m3 + .file("m3/Cargo.toml", &basic_lib_manifest("m3")) + .file("m3/src/lib.rs", "") + .build(); + + // dep (outside of workspace) + let _dep = project() + .at("dep") + .file("Cargo.toml", &basic_lib_manifest("dep")) + .file("src/lib.rs", "") + .build(); + + // Profiles should be: + // m3: 4 (as build.rs dependency) + // m3: 1 (as [profile.dev] as workspace member) + // dep: 3 (as [profile.dev.package."*"] as non-workspace member) + // m1 build.rs: 4 (as [profile.dev.build-override]) + // m2 build.rs: 2 (as [profile.dev.package.m2]) + // m2: 2 (as [profile.dev.package.m2]) + // m1: 1 (as [profile.dev]) + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] m3 v0.5.0 ([ROOT]/foo/m3) +[COMPILING] dep v0.5.0 ([ROOT]/dep) +[RUNNING] `rustc --crate-name m3 --edition=2015 m3/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=4 [..]` +[RUNNING] `rustc --crate-name dep [..][ROOT]/dep/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=3 [..]` +[RUNNING] `rustc --crate-name m3 --edition=2015 m3/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=1 [..]` +[RUNNING] `rustc --crate-name build_script_build --edition=2015 m1/build.rs [..] --crate-type bin --emit=[..]link[..]-C codegen-units=4 [..]` +[COMPILING] m2 v0.0.1 ([ROOT]/foo/m2) +[RUNNING] `rustc --crate-name build_script_build --edition=2015 m2/build.rs [..] --crate-type bin --emit=[..]link[..]-C codegen-units=2 [..]` +[RUNNING] `[ROOT]/foo/target/debug/build/m1-[HASH]/build-script-build` +[RUNNING] `[ROOT]/foo/target/debug/build/m2-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name m2 --edition=2015 m2/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=2 [..]` +[COMPILING] m1 v0.0.1 ([ROOT]/foo/m1) +[RUNNING] `rustc --crate-name m1 --edition=2015 m1/src/lib.rs [..] --crate-type lib --emit=[..]link[..]-C codegen-units=1 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn profile_override_spec_multiple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [profile.dev.package.bar] + opt-level = 3 + + [profile.dev.package."bar:0.5.0"] + opt-level = 3 + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] multiple package overrides in profile `dev` match package `bar v0.5.0 ([ROOT]/foo/bar)` +found package specs: bar, bar@0.5.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_override_spec_with_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [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_data(str![[r#" +... +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[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" + edition = "2015" + + [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_data(str![[r#" +... +[CHECKING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc [..]bar/src/lib.rs [..] -C codegen-units=2 [..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn profile_override_spec() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["m1", "m2"] + + [profile.dev.package."dep:1.0.0"] + codegen-units = 1 + + [profile.dev.package."dep:2.0.0"] + codegen-units = 2 + "#, + ) + // m1 + .file( + "m1/Cargo.toml", + r#" + [package] + name = "m1" + version = "0.0.1" + edition = "2015" + + [dependencies] + dep = { path = "../../dep1" } + "#, + ) + .file("m1/src/lib.rs", "extern crate dep;") + // m2 + .file( + "m2/Cargo.toml", + r#" + [package] + name = "m2" + version = "0.0.1" + edition = "2015" + + [dependencies] + dep = {path = "../../dep2" } + "#, + ) + .file("m2/src/lib.rs", "extern crate dep;") + .build(); + + project() + .at("dep1") + .file("Cargo.toml", &basic_manifest("dep", "1.0.0")) + .file("src/lib.rs", "") + .build(); + + project() + .at("dep2") + .file("Cargo.toml", &basic_manifest("dep", "2.0.0")) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -v") + .with_stderr_data( + str![[r#" +... +[RUNNING] `rustc [..][ROOT]/dep1/src/lib.rs [..] -C codegen-units=1 [..]` +[RUNNING] `rustc [..][ROOT]/dep2/src/lib.rs [..] -C codegen-units=2 [..]` +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn override_proc_macro() { + Package::new("shared", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + shared = "1.0" + pm = {path = "pm"} + + [profile.dev.build-override] + codegen-units = 4 + "#, + ) + .file("src/lib.rs", r#"pm::eat!{}"#) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + edition = "2015" + + [lib] + proc-macro = true + + [dependencies] + shared = "1.0" + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro] + pub fn eat(_item: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .build(); + + p.cargo("check -v") + // Shared built for the proc-macro. + .with_stderr_data(str![[r#" +... +[RUNNING] `rustc [..]--crate-name shared [..] -C codegen-units=4[..]` +... +[RUNNING] `rustc [..]--crate-name pm [..] -C codegen-units=4[..]` +... +"#]]) + // Shared built for the library. + .with_stderr_line_without( + &["[RUNNING] `rustc --crate-name shared --edition=2015"], + &["-C codegen-units"], + ) + .with_stderr_line_without( + &["[RUNNING] `rustc [..]--crate-name foo"], + &["-C codegen-units"], + ) + .run(); +} + +#[cargo_test] +fn no_warning_ws() { + // https://github.com/rust-lang/cargo/issues/7378, avoid warnings in a workspace. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + + [profile.dev.package.a] + codegen-units = 3 + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("check -p b") + .with_stderr_data(str![[r#" +[CHECKING] b v0.1.0 ([ROOT]/foo/b) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_override_shared() { + // A dependency with a build script that is shared with a build + // dependency, using different profile settings. That is: + // + // foo DEBUG=2 + // ├── common DEBUG=2 + // │ └── common Run build.rs DEBUG=2 + // │ └── common build.rs DEBUG=0 (build_override) + // └── foo Run build.rs DEBUG=2 + // └── foo build.rs DEBUG=0 (build_override) + // └── common DEBUG=0 (build_override) + // └── common Run build.rs DEBUG=0 (build_override) + // └── common build.rs DEBUG=0 (build_override) + // + // The key part here is that `common` RunCustomBuild is run twice, once + // with DEBUG=2 (as a dependency of foo) and once with DEBUG=0 (as a + // build-dependency of foo's build script). + Package::new("common", "1.0.0") + .file( + "build.rs", + r#" + fn main() { + if std::env::var("DEBUG").unwrap() != "false" { + println!("cargo::rustc-cfg=foo_debug"); + } else { + println!("cargo::rustc-cfg=foo_release"); + } + } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { + if cfg!(foo_debug) { + assert!(cfg!(debug_assertions)); + 1 + } else if cfg!(foo_release) { + assert!(!cfg!(debug_assertions)); + 2 + } else { + panic!("not set"); + } + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [build-dependencies] + common = "1.0" + + [dependencies] + common = "1.0" + + [profile.dev.build-override] + debug = 0 + debug-assertions = false + "#, + ) + .file( + "build.rs", + r#" + fn main() { + assert_eq!(common::foo(), 2); + } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + assert_eq!(common::foo(), 1); + } + "#, + ) + .build(); + + p.cargo("run").run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_targets.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_targets.rs new file mode 100644 index 000000000..c95369966 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_targets.rs @@ -0,0 +1,733 @@ +//! Tests for checking exactly how profiles correspond with each unit. For +//! example, the `test` profile applying to test targets, but not other +//! targets, etc. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, project, str, Project}; + +fn all_target_project() -> Project { + // This abuses the `codegen-units` setting so that we can verify exactly + // which profile is used for each compiler invocation. + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [build-dependencies] + bdep = { path = "bdep" } + + [profile.dev] + codegen-units = 1 + panic = "abort" + [profile.release] + codegen-units = 2 + panic = "abort" + [profile.test] + codegen-units = 3 + [profile.bench] + codegen-units = 4 + [profile.dev.build-override] + codegen-units = 5 + [profile.release.build-override] + codegen-units = 6 + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file("src/main.rs", "extern crate foo; fn main() {}") + .file("examples/ex1.rs", "extern crate foo; fn main() {}") + .file("tests/test1.rs", "extern crate foo;") + .file("benches/bench1.rs", "extern crate foo;") + .file( + "build.rs", + r#" + extern crate bdep; + fn main() { + eprintln!("foo custom build PROFILE={} DEBUG={} OPT_LEVEL={}", + std::env::var("PROFILE").unwrap(), + std::env::var("DEBUG").unwrap(), + std::env::var("OPT_LEVEL").unwrap(), + ); + } + "#, + ) + // `bar` package. + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + // `bdep` package. + .file( + "bdep/Cargo.toml", + r#" + [package] + name = "bdep" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "../bar" } + "#, + ) + .file("bdep/src/lib.rs", "extern crate bar;") + .build() +} + +#[cargo_test] +fn profile_selection_build() { + let p = all_target_project(); + + // `build` + // NOTES: + // - bdep `panic` is not set because it thinks `build.rs` is a plugin. + // - build_script_build is built without panic because it thinks `build.rs` is a plugin. + // - We make sure that the build dependencies bar, bdep, and build.rs + // are built with debuginfo=0. + p.cargo("build -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..] +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..] +[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..] +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .with_stderr_does_not_contain("[..] -C debuginfo=0[..]") + .run(); + p.cargo("build -vv") + .with_stderr_data( + str![[r#" +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_build_release() { + let p = all_target_project(); + + // `build --release` + p.cargo("build --release -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..] +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..] +[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..] +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); + p.cargo("build --release -vv") + .with_stderr_data( + str![[r#" +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_build_all_targets() { + let p = all_target_project(); + // `build` + // NOTES: + // - bdep `panic` is not set because it thinks `build.rs` is a plugin. + // - build_script_build is built without panic because it thinks + // `build.rs` is a plugin. + // - Benchmark dependencies are compiled in `dev` mode, which may be + // surprising. See issue rust-lang/cargo#4929. + // - We make sure that the build dependencies bar, bdep, and build.rs are built with + // debuginfo=0; but since we don't pass `-C debuginfo` when it's set to 0, we have to test + // explicitly that there's no `-C debuginfo` flag. + // + // - Dependency profiles: + // Pkg Target Profile Reason + // --- ------ ------- ------ + // bar lib dev For foo-bin + // bar lib dev-panic For tests/benches and bdep + // bdep lib dev-panic For foo build.rs + // foo custom dev-panic + // + // - `foo` target list is: + // Target Profile Mode + // ------ ------- ---- + // lib dev+panic build (a normal lib target) + // lib dev-panic build (used by tests/benches) + // lib dev dev + // test dev dev + // bench dev dev + // bin dev dev + // bin dev build + // example dev build + p.cargo("build --all-targets -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=5 [..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]` +[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]link[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .with_stderr_does_not_contain("[..] -C debuginfo=0[..]") + .run(); + p.cargo("build -vv") + .with_stderr_data( + str![[r#" +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_build_all_targets_release() { + let p = all_target_project(); + // `build --all-targets --release` + // NOTES: + // - bdep `panic` is not set because it thinks `build.rs` is a plugin. + // - bar compiled twice. It tries with and without panic, but the "is a + // plugin" logic is forcing it to be cleared. + // - build_script_build is built without panic because it thinks + // `build.rs` is a plugin. + // - build_script_build is being run two times. Once for the `dev` and + // `test` targets, once for the `bench` targets. + // TODO: "PROFILE" says debug both times, though! + // + // - Dependency profiles: + // Pkg Target Profile Reason + // --- ------ ------- ------ + // bar lib release For foo-bin + // bar lib release-panic For tests/benches and bdep + // bdep lib release-panic For foo build.rs + // foo custom release-panic + // + // - `foo` target list is: + // Target Profile Mode + // ------ ------- ---- + // lib release+panic build (a normal lib target) + // lib release-panic build (used by tests/benches) + // lib release test (bench/test de-duped) + // test release test + // bench release test + // bin release test (bench/test de-duped) + // bin release build + // example release build + p.cargo("build --all-targets --release -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C embed-bitcode=[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C embed-bitcode=[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=6 [..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]` +[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]` +[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); + p.cargo("build --all-targets --release -vv") + .with_stderr_data( + str![[r#" +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_test() { + let p = all_target_project(); + // `test` + // NOTES: + // - Dependency profiles: + // Pkg Target Profile Reason + // --- ------ ------- ------ + // bar lib test For foo-bin + // bar lib test-panic For tests/benches and bdep + // bdep lib test-panic For foo build.rs + // foo custom test-panic + // + // - `foo` target list is: + // Target Profile Mode + // ------ ------- ---- + // lib test-panic build (for tests) + // lib test build (for bins) + // lib test test + // test test test + // example test-panic build + // bin test test + // bin test build + // + p.cargo("test -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=3 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=5 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C embed-bitcode=[..]-C codegen-units=3 -C debuginfo=2 [..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]` +[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C panic=abort[..]-C codegen-units=3 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C panic=abort[..]-C codegen-units=3 -C debuginfo=2 [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/debug/deps/test1-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `[..] rustdoc [..]--test [..] + +"#]].unordered()) + .run(); + p.cargo("test -vv") + .with_stderr_data( + str![[r#" +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/debug/deps/test1-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `[..] rustdoc [..]--test [..] + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_test_release() { + let p = all_target_project(); + + // `test --release` + // NOTES: + // - Dependency profiles: + // Pkg Target Profile Reason + // --- ------ ------- ------ + // bar lib release For foo-bin + // bar lib release-panic For tests/benches and bdep + // bdep lib release-panic For foo build.rs + // foo custom release-panic + // + // - `foo` target list is: + // Target Profile Mode + // ------ ------- ---- + // lib release-panic build (for tests) + // lib release build (for bins) + // lib release test + // test release test + // example release-panic build + // bin release test + // bin release build + // + p.cargo("test --release -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C opt-level=3[..]-C codegen-units=2[..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]` +[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]` +[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=2 --test [..]` +[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]link -C opt-level=3[..]-C codegen-units=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/release/deps/test1-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `[..] rustdoc [..]--test [..]` + +"#]].unordered()) + .run(); + p.cargo("test --release -vv") + .with_stderr_data( + str![[r#" +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[..][ROOT]/foo/target/release/deps/test1-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `[..] rustdoc [..]--test [..] + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_bench() { + let p = all_target_project(); + + // `bench` + // NOTES: + // - Dependency profiles: + // Pkg Target Profile Reason + // --- ------ ------- ------ + // bar lib bench For foo-bin + // bar lib bench-panic For tests/benches and bdep + // bdep lib bench-panic For foo build.rs + // foo custom bench-panic + // + // - `foo` target list is: + // Target Profile Mode + // ------ ------- ---- + // lib bench-panic build (for benches) + // lib bench build (for bins) + // lib bench test(bench) + // bench bench test(bench) + // bin bench test(bench) + // bin bench build + // + p.cargo("bench -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C embed-bitcode=[..]-C codegen-units=4 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort -C embed-bitcode=[..]-C codegen-units=4 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=6 [..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..]` +[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=4 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..]-C codegen-units=4 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=4 --test [..]` +[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=4 --test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link -C opt-level=3[..]-C codegen-units=4 --test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link -C opt-level=3 -C panic=abort[..]-C codegen-units=4 [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench` +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench` +[RUNNING] `[..][ROOT]/foo/target/release/deps/bench1-[HASH][EXE] --bench` + +"#]].unordered()) + .run(); + p.cargo("bench -vv") + .with_stderr_data( + str![[r#" +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench` +[RUNNING] `[..][ROOT]/foo/target/release/deps/foo-[HASH][EXE] --bench` +[RUNNING] `[..][ROOT]/foo/target/release/deps/bench1-[HASH][EXE] --bench` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_check_all_targets() { + let p = all_target_project(); + // `check` + // NOTES: + // - Dependency profiles: + // Pkg Target Profile Action Reason + // --- ------ ------- ------ ------ + // bar lib dev* link For bdep + // bar lib dev-panic metadata For tests/benches + // bar lib dev metadata For lib/bins + // bdep lib dev* link For foo build.rs + // foo custom dev* link For build.rs + // + // `*` = wants panic, but it is cleared when args are built. + // + // - foo target list is: + // Target Profile Mode + // ------ ------- ---- + // lib dev check + // lib dev-panic check (for tests/benches) + // lib dev-panic check-test (checking lib as a unittest) + // example dev check + // test dev-panic check-test + // bench dev-panic check-test + // bin dev check + // bin dev-panic check-test (checking bin as a unittest) + // + p.cargo("check --all-targets -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link -C embed-bitcode=[..]-C codegen-units=5 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort -C embed-bitcode=[..]-C codegen-units=1 -C debuginfo=2 [..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]` +[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]metadata[..]-C codegen-units=1 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); + // Starting with Rust 1.27, rustc emits `rmeta` files for bins, so + // everything should be completely fresh. Previously, bins were being + // rechecked. + // See PR rust-lang/rust#49289 and issue rust-lang/cargo#3624. + p.cargo("check --all-targets -vv") + .with_stderr_data( + str![[r#" +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_check_all_targets_release() { + let p = all_target_project(); + // `check --release` + // See issue rust-lang/cargo#5218. + // This is a pretty straightforward variant of + // `profile_selection_check_all_targets` that uses `release` instead of + // `dev` for all targets. + p.cargo("check --all-targets --release -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=6 [..] +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 [..] +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link [..]-C codegen-units=6 [..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=6 [..] +[RUNNING] `[..][ROOT]/foo/target/release/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=release DEBUG=false OPT_LEVEL=3 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]metadata -C opt-level=3[..]-C codegen-units=2 --test [..] +[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type bin --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..] +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]metadata -C opt-level=3 -C panic=abort[..]-C codegen-units=2 [..] +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); + + p.cargo("check --all-targets --release -vv") + .with_stderr_data( + str![[r#" +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_check_all_targets_test() { + let p = all_target_project(); + + // `check --profile=test` + // - Dependency profiles: + // Pkg Target Profile Action Reason + // --- ------ ------- ------ ------ + // bar lib test* link For bdep + // bar lib test-panic metadata For tests/benches + // bdep lib test* link For foo build.rs + // foo custom test* link For build.rs + // + // `*` = wants panic, but it is cleared when args are built. + // + // - foo target list is: + // Target Profile Mode + // ------ ------- ---- + // lib test-panic check-test (for tests/benches) + // lib test-panic check-test (checking lib as a unittest) + // example test-panic check-test + // test test-panic check-test + // bench test-panic check-test + // bin test-panic check-test + // + p.cargo("check --all-targets --profile=test -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]` +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]` +[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/lib.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name test1 --edition=2015 tests/test1.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name bench1 --edition=2015 benches/bench1.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[RUNNING] `[..] rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--emit=[..]metadata[..]-C codegen-units=3 -C debuginfo=2 [..]--test [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered()) + .run(); + + p.cargo("check --all-targets --profile=test -vv") + .with_stderr_data( + str![[r#" +[FRESH] bdep v0.0.1 ([ROOT]/foo/bdep) +[FRESH] bar v0.0.1 ([ROOT]/foo/bar) +[FRESH] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn profile_selection_doc() { + let p = all_target_project(); + // `doc` + // NOTES: + // - Dependency profiles: + // Pkg Target Profile Action Reason + // --- ------ ------- ------ ------ + // bar lib dev* link For bdep + // bar lib dev metadata For rustdoc + // bdep lib dev* link For foo build.rs + // foo custom dev* link For build.rs + // + // `*` = wants panic, but it is cleared when args are built. + p.cargo("doc -vv") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[DOCUMENTING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]` +[RUNNING] `[..] rustdoc [..]--crate-name bar bar/src/lib.rs [..] +[RUNNING] `[..] rustc --crate-name bar --edition=2015 bar/src/lib.rs [..]--crate-type lib --emit=[..]metadata -C panic=abort[..]-C codegen-units=1 -C debuginfo=2 [..]` +[COMPILING] bdep v0.0.1 ([ROOT]/foo/bdep) +[RUNNING] `[..] rustc --crate-name bdep --edition=2015 bdep/src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C codegen-units=5 [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name build_script_build --edition=2015 build.rs [..]--crate-type bin --emit=[..]link[..]-C codegen-units=5 [..]` +[RUNNING] `[..][ROOT]/foo/target/debug/build/foo-[HASH]/build-script-build` +[foo 0.0.1] foo custom build PROFILE=debug DEBUG=true OPT_LEVEL=0 +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustdoc [..]--crate-name foo src/lib.rs [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]].unordered()) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_trim_paths.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_trim_paths.rs new file mode 100644 index 000000000..9340a523d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profile_trim_paths.rs @@ -0,0 +1,851 @@ +//! Tests for `-Ztrim-paths`. + +use cargo_test_support::basic_manifest; +use cargo_test_support::git; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +#[cargo_test] +fn gated_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + trim-paths = "macro" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `trim-paths` is required +... +"#]]) + .run(); +} + +#[cargo_test] +fn gated_config_toml() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [profile.dev] + trim-paths = "macro" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] config profile `dev` is not valid (defined in `[ROOT]/foo/.cargo/config.toml`) + +Caused by: + feature `trim-paths` is required +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn release_profile_default_to_object() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --release --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn one_option() { + let build = |option| { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + trim-paths = "{option}" + "# + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v -Ztrim-paths") + }; + + for option in ["macro", "diagnostics", "object", "all"] { + build(option) + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(&format!( + "\ +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]\ + -Zremap-path-scope={option} \ + --remap-path-prefix=[ROOT]/foo=. \ + --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + )) + .run(); + } + build("none") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_does_not_contain("[..]-Zremap-path-scope=[..]") + .with_stderr_does_not_contain("[..]--remap-path-prefix=[..]") + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn multiple_options() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + trim-paths = ["diagnostics", "macro", "object"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=diagnostics,macro,object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn profile_merge_works() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + trim-paths = ["macro"] + + [profile.custom] + inherits = "dev" + trim-paths = ["diagnostics"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v -Ztrim-paths --profile custom") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=diagnostics --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `custom` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn registry_dependency() { + Package::new("bar", "0.0.1") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", r#"pub fn f() { println!("{}", file!()); }"#) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.0.1" + + [profile.dev] + trim-paths = "object" + "#, + ) + .file("src/main.rs", "fn main() { bar::f(); }") + .build(); + + p.cargo("run --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stdout_data(str![[r#" +[..]/bar-0.0.1/src/lib.rs + +"#]]) // Omit the hash of Source URL + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn git_dependency() { + let git_project = git::new("bar", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", r#"pub fn f() { println!("{}", file!()); }"#) + }); + let url = git_project.url(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = {{ git = "{url}" }} + + [profile.dev] + trim-paths = "object" + "# + ), + ) + .file("src/main.rs", "fn main() { bar::f(); }") + .build(); + + p.cargo("run --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stdout_data(str![[r#" +[..]/[..]/src/lib.rs + +"#]]) // Omit the hash of Source URL and commit + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/bar` +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOTURL]/bar#[..]) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/home/.cargo/git/checkouts= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn path_dependency() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "cocktail-bar" } + + [profile.dev] + trim-paths = "object" + "#, + ) + .file("src/main.rs", "fn main() { bar::f(); }") + .file("cocktail-bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "cocktail-bar/src/lib.rs", + r#"pub fn f() { println!("{}", file!()); }"#, + ) + .build(); + + p.cargo("run --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stdout_data(str![[r#" +cocktail-bar/src/lib.rs + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/cocktail-bar) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn path_dependency_outside_workspace() { + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", r#"pub fn f() { println!("{}", file!()); }"#) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "../bar" } + + [profile.dev] + trim-paths = "object" + "#, + ) + .file("src/main.rs", "fn main() { bar::f(); }") + .build(); + + p.cargo("run --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stdout_data(str![[r#" +bar-0.0.1/src/lib.rs + +"#]]) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/bar) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/bar=bar-0.0.1 --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn diagnostics_works() { + Package::new("bar", "0.0.1") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", r#"pub fn f() { let unused = 0; }"#) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.0.1" + + [profile.dev] + trim-paths = "diagnostics" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let registry_src = paths::home().join(".cargo/registry/src"); + let registry_src = registry_src.display(); + + p.cargo("build -vv -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_line_without( + &["[..]bar-0.0.1/src/lib.rs:1[..]"], + &[&format!("{registry_src}")], + ) + .with_stderr_data(str![[r#" +... +[RUNNING] `[..] rustc [..]-Zremap-path-scope=diagnostics --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[WARNING] unused variable: `unused` +... +[RUNNING] `[..] rustc [..]-Zremap-path-scope=diagnostics --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +... +"#]]) + .run(); +} + +#[cfg(target_os = "macos")] +mod object_works { + use super::*; + + fn inspect_debuginfo(path: &std::path::Path) -> Vec { + std::process::Command::new("nm") + .arg("-pa") + .arg(path) + .output() + .expect("nm works") + .stdout + } + + #[cargo_test(requires = "nm", nightly, reason = "-Zremap-path-scope is unstable")] + fn with_split_debuginfo_off() { + object_works_helper("off", inspect_debuginfo); + } + + #[cargo_test(requires = "nm", nightly, reason = "-Zremap-path-scope is unstable")] + fn with_split_debuginfo_packed() { + object_works_helper("packed", inspect_debuginfo); + } + + #[cargo_test(requires = "nm", nightly, reason = "-Zremap-path-scope is unstable")] + fn with_split_debuginfo_unpacked() { + object_works_helper("unpacked", inspect_debuginfo); + } +} + +#[cfg(target_os = "linux")] +mod object_works { + use super::*; + + fn inspect_debuginfo(path: &std::path::Path) -> Vec { + std::process::Command::new("readelf") + .arg("--debug-dump=info") + .arg("--debug-dump=no-follow-links") // older version can't recognized but just a warning + .arg(path) + .output() + .expect("readelf works") + .stdout + } + + #[cargo_test( + requires = "readelf", + nightly, + reason = "-Zremap-path-scope is unstable" + )] + fn with_split_debuginfo_off() { + object_works_helper("off", inspect_debuginfo); + } + + #[cargo_test( + requires = "readelf", + nightly, + reason = "-Zremap-path-scope is unstable" + )] + fn with_split_debuginfo_packed() { + object_works_helper("packed", inspect_debuginfo); + } + + #[cargo_test( + requires = "readelf", + nightly, + reason = "-Zremap-path-scope is unstable" + )] + fn with_split_debuginfo_unpacked() { + object_works_helper("unpacked", inspect_debuginfo); + } +} + +#[cfg(unix)] +fn object_works_helper(split_debuginfo: &str, run: impl Fn(&std::path::Path) -> Vec) { + use std::os::unix::ffi::OsStrExt; + + let registry_src = paths::home().join(".cargo/registry/src"); + let registry_src_bytes = registry_src.as_os_str().as_bytes(); + let rust_src = "/lib/rustc/src/rust".as_bytes(); + + Package::new("bar", "0.0.1") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", r#"pub fn f() { println!("{}", file!()); }"#) + .publish(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.0.1" + + [profile.dev] + split-debuginfo = "{split_debuginfo}" + "# + ), + ) + .file("src/main.rs", "fn main() { bar::f(); }") + .build(); + + let pkg_root = p.root(); + let pkg_root = pkg_root.as_os_str().as_bytes(); + + p.cargo("build").run(); + + let bin_path = p.bin("foo"); + assert!(bin_path.is_file()); + let stdout = run(&bin_path); + // TODO: re-enable this check when rustc bootstrap disables remapping + // + // assert!(memchr::memmem::find(&stdout, rust_src).is_some()); + assert!(memchr::memmem::find(&stdout, registry_src_bytes).is_some()); + assert!(memchr::memmem::find(&stdout, pkg_root).is_some()); + + p.cargo("clean").run(); + + p.cargo("build --verbose -Ztrim-paths") + .arg("--config") + .arg(r#"profile.dev.trim-paths="object""#) + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(&format!( + "\ +[COMPILING] bar v0.0.1 +[RUNNING] `rustc [..]-C split-debuginfo={split_debuginfo} [..]\ + -Zremap-path-scope=object \ + --remap-path-prefix=[ROOT]/home/.cargo/registry/src= \ + --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-C split-debuginfo={split_debuginfo} [..]\ + -Zremap-path-scope=object \ + --remap-path-prefix=[ROOT]/foo=. \ + --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + )) + .run(); + + let bin_path = p.bin("foo"); + assert!(bin_path.is_file()); + let stdout = run(&bin_path); + assert!(memchr::memmem::find(&stdout, rust_src).is_none()); + for line in stdout.split(|c| c == &b'\n') { + let registry = memchr::memmem::find(line, registry_src_bytes).is_none(); + let local = memchr::memmem::find(line, pkg_root).is_none(); + if registry && local { + continue; + } + + #[cfg(target_os = "macos")] + { + // `OSO` symbols can't be trimmed at this moment. + // See + if memchr::memmem::find(line, b" OSO ").is_some() { + continue; + } + + // on macOS `SO` symbols are embedded in final binaries and should be trimmed. + // See rust-lang/rust#117652. + if memchr::memmem::find(line, b" SO ").is_some() { + continue; + } + } + + #[cfg(target_os = "linux")] + { + // There is a bug in rustc `-Zremap-path-scope`. + // See rust-lang/rust/pull/118518 + if memchr::memmem::find(line, b"DW_AT_comp_dir").is_some() { + continue; + } + if memchr::memmem::find(line, b"DW_AT_GNU_dwo_name").is_some() { + continue; + } + } + + panic!( + "unexpected untrimmed symbol: {}", + String::from_utf8(line.into()).unwrap() + ); + } +} + +// TODO: might want to move to test/testsuite/build_script.rs once stabilized. +#[cargo_test(nightly, reason = "-Zremap-path-scope is unstable")] +fn custom_build_env_var_trim_paths() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "") + .build(); + + let test_cases = [ + ("[]", "none"), + ("\"all\"", "all"), + ("\"diagnostics\"", "diagnostics"), + ("\"macro\"", "macro"), + ("\"none\"", "none"), + ("\"object\"", "object"), + ("false", "none"), + ("true", "all"), + ( + r#"["diagnostics", "macro", "object"]"#, + "diagnostics,macro,object", + ), + ]; + + for (opts, expected) in test_cases { + p.change_file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + trim-paths = {opts} + "# + ), + ); + + p.change_file( + "build.rs", + &format!( + r#" + fn main() {{ + assert_eq!( + std::env::var("CARGO_TRIM_PATHS").unwrap().as_str(), + "{expected}", + ); + }} + "# + ), + ); + + p.cargo("build -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .run(); + } +} + +#[cfg(unix)] +#[cargo_test(requires = "lldb", nightly, reason = "-Zremap-path-scope is unstable")] +fn lldb_works_after_trimmed() { + use cargo_test_support::compare::assert_e2e; + use cargo_util::is_ci; + + if !is_ci() { + // On macOS lldb requires elevated privileges to run developer tools. + // See rust-lang/cargo#13413 + return; + } + + let run_lldb = |path| { + std::process::Command::new("lldb") + .args(["-o", "breakpoint set --file src/main.rs --line 4"]) + .args(["-o", "run"]) + .args(["-o", "continue"]) + .args(["-o", "exit"]) + .arg("--no-use-colors") + .arg(path) + .output() + .expect("lldb works") + }; + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + trim-paths = "object" + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + let msg = "Hello, Ferris!"; + println!("{msg}"); + } + "#, + ) + .build(); + + p.cargo("build --verbose -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-Zremap-path-scope=object --remap-path-prefix=[ROOT]/foo=. --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let bin_path = p.bin("foo"); + assert!(bin_path.is_file()); + let stdout = String::from_utf8(run_lldb(bin_path).stdout).unwrap(); + assert_e2e().eq( + &stdout, + str![[r#" +... +[..]stopped[..] +[..]stop reason = breakpoint 1.1[..] +... +(lldb) continue +Hello, Ferris! +... + +"#]], + ); +} + +#[cargo_test(nightly, reason = "rustdoc --remap-path-prefix is unstable")] +fn rustdoc_without_diagnostics_scope() { + Package::new("bar", "0.0.1") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "src/lib.rs", + r#" + /// + pub struct Bar; + "#, + ) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.0.1" + + [profile.dev] + trim-paths = "object" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc -vv -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(str![[r#" +... +[WARNING] unopened HTML tag `script` + --> [ROOT]/home/.cargo/registry/src/-[HASH]/bar-0.0.1/src/lib.rs:2:17 +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "rustdoc --remap-path-prefix is unstable")] +fn rustdoc_diagnostics_works() { + // This is expected to work after rust-lang/rust#128736 + Package::new("bar", "0.0.1") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "src/lib.rs", + r#" + /// + pub struct Bar; + "#, + ) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "0.0.1" + + [profile.dev] + trim-paths = "diagnostics" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("doc -vv -Ztrim-paths") + .masquerade_as_nightly_cargo(&["-Ztrim-paths"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `[..]rustc [..]-Zremap-path-scope=diagnostics --remap-path-prefix=[ROOT]/home/.cargo/registry/src= --remap-path-prefix=[..]/lib/rustlib/src/rust=/rustc/[..]` +... +[WARNING] unopened HTML tag `script` + --> -[..]/bar-0.0.1/src/lib.rs:2:17 +... +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profiles.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profiles.rs new file mode 100644 index 000000000..36a703910 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/profiles.rs @@ -0,0 +1,878 @@ +//! Tests for profiles. + +use std::env; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{project, rustc_host, str}; + +#[cargo_test] +fn profile_overrides() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "test" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.dev] + opt-level = 1 + debug = false + rpath = true + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build -v").with_stderr_data(str![[r#" +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..] -C opt-level=1[..] -C debug-assertions=on[..] -C metadata=[..] -C rpath --out-dir [ROOT]/foo/target/debug/deps [..] -L dependency=[ROOT]/foo/target/debug/deps` +[FINISHED] `dev` profile [optimized] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn opt_level_override_0() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "test" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.dev] + opt-level = 0 + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build -v").with_stderr_data(str![[r#" +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..] -C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn debug_override_1() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.dev] + debug = 1 + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build -v").with_stderr_data(str![[r#" +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=1 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +fn check_opt_level_override(profile_level: &str, rustc_level: &str) { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + + name = "test" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.dev] + opt-level = {level} + "#, + level = profile_level + ), + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build -v") + .with_stderr_data(&format!( + "\ +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib \ + --emit=[..]link \ + -C opt-level={level}[..]\ + -C debuginfo=2 [..]\ + -C debug-assertions=on[..] \ + -C metadata=[..] \ + --out-dir [..] \ + -L dependency=[ROOT]/foo/target/debug/deps` +[FINISHED] `dev` profile [..]+ debuginfo] target(s) in [ELAPSED]s +", + level = rustc_level + )) + .run(); +} + +#[cargo_test] +fn opt_level_overrides() { + for &(profile_level, rustc_level) in &[ + ("1", "1"), + ("2", "2"), + ("3", "3"), + ("\"s\"", "s"), + ("\"z\"", "z"), + ] { + check_opt_level_override(profile_level, rustc_level) + } +} + +#[cargo_test] +fn top_level_overrides_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + + name = "test" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.release] + opt-level = 1 + debug = true + + [dependencies.foo] + path = "foo" + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + + name = "foo" + version = "0.0.0" + edition = "2015" + authors = [] + + [profile.release] + opt-level = 0 + debug = false + + [lib] + name = "foo" + crate-type = ["dylib", "rlib"] + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + p.cargo("build -v --release") + .with_stderr_data(&format!( + "\ +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.0 ([ROOT]/foo/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 foo/src/lib.rs [..]\ + --crate-type dylib --crate-type rlib \ + --emit=[..]link \ + -C prefer-dynamic \ + -C opt-level=1[..]\ + -C debuginfo=2 [..]\ + -C metadata=[..] \ + --out-dir [ROOT]/foo/target/release/deps \ + -L dependency=[ROOT]/foo/target/release/deps` +[COMPILING] test v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test --edition=2015 src/lib.rs [..]--crate-type lib \ + --emit=[..]link \ + -C opt-level=1[..]\ + -C debuginfo=2 [..]\ + -C metadata=[..] \ + --out-dir [..] \ + -L dependency=[ROOT]/foo/target/release/deps \ + --extern foo=[ROOT]/foo/target/release/deps/\ + {prefix}foo[..]{suffix} \ + --extern foo=[ROOT]/foo/target/release/deps/libfoo.rlib` +[FINISHED] `release` profile [optimized + debuginfo] target(s) in [ELAPSED]s +", + prefix = env::consts::DLL_PREFIX, + suffix = env::consts::DLL_SUFFIX + )) + .run(); +} + +#[cargo_test] +fn profile_in_non_root_manifest_triggers_a_warning() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + + [profile.dev] + debug = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + + [profile.dev] + opt-level = 1 + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .cwd("bar") + .with_stderr_data(str![[r#" +[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root: +package: [ROOT]/foo/bar/Cargo.toml +workspace: [ROOT]/foo/Cargo.toml +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_in_virtual_manifest_works() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + + [profile.dev] + opt-level = 1 + debug = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .cwd("bar") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.1.0 ([ROOT]/foo/bar) +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_lto_string_bool_dev() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.dev] + lto = "true" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + `lto` setting of string `"true"` for `dev` profile is not a valid setting, must be a boolean (`true`/`false`) or a string (`"thin"`/`"fat"`/`"off"`) or omitted. + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_panic_test_bench() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.test] + panic = "abort" + + [profile.bench] + panic = "abort" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] `panic` setting is ignored for `bench` profile +[WARNING] `panic` setting is ignored for `test` profile +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn profile_doc_deprecated() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [profile.doc] + opt-level = 0 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] profile `doc` is deprecated and has no effect +... +"#]]) + .run(); +} + +#[cargo_test] +fn panic_unwind_does_not_build_twice() { + // Check for a bug where `lib` was built twice, once with panic set and + // once without. Since "unwind" is the default, they are the same and + // should only be built once. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.dev] + panic = "unwind" + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .file("tests/t1.rs", "") + .build(); + + p.cargo("test -v --tests --no-run") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --test [..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin [..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..] --test [..]` +[RUNNING] `rustc --crate-name t1 --edition=2015 tests/t1.rs [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/t1-[HASH][EXE]` + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn debug_0_report() { + // The finished line handles 0 correctly. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.dev] + debug = 0 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s + +"#]]) + .with_stderr_does_not_contain("-C debuginfo") + .run(); +} + +#[cargo_test] +fn thin_lto_works() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "top" + version = "0.5.0" + edition = "2015" + authors = [] + + [profile.release] + lto = 'thin' + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release -v") + .with_stderr_data(str![[r#" +[COMPILING] top v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C lto=thin [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn strip_works() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.release] + strip = 'symbols' + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C strip=symbols [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn strip_passes_unknown_option_to_rustc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.release] + strip = 'unknown' + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release -v") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C strip=unknown [..]` +[ERROR] incorrect value `unknown` for [..] `strip` [..] was expected +... +"#]]) + .run(); +} + +#[cargo_test] +fn strip_accepts_true_to_strip_symbols() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.release] + strip = true + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C strip=symbols [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn strip_accepts_false_to_disable_strip() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.release] + strip = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release -v") + .with_stderr_does_not_contain("[RUNNING] `rustc [..] -C strip[..]`") + .run(); +} + +#[cargo_test] +fn strip_debuginfo_in_release() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --release -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C strip=debuginfo[..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build --release -v --target") + .arg(rustc_host()) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] -C strip=debuginfo[..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn strip_debuginfo_without_debug() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [profile.dev] + debug = 0 + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C strip=debuginfo[..]` +[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn do_not_strip_debuginfo_with_requested_debug() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [profile.release.package.bar] + debug = 1 + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build --release -v") + .with_stderr_does_not_contain("[RUNNING] `rustc [..] -C strip=debuginfo[..]`") + .run(); +} + +#[cargo_test] +fn rustflags_works() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["profile-rustflags"] + + [profile.dev] + rustflags = ["-C", "link-dead-code=yes"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustflags_works_with_env() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["profile-rustflags"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .env("CARGO_PROFILE_DEV_RUSTFLAGS", "-C link-dead-code=yes") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C link-dead-code=yes [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustflags_requires_cargo_feature() { + let p = project() + .file( + "Cargo.toml", + r#" + [profile.dev] + rustflags = ["-C", "link-dead-code=yes"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `profile-rustflags` is required + + The package requires the Cargo feature called `profile-rustflags`, but that feature is not stabilized in this version of Cargo (1.[..]). + Consider adding `cargo-features = ["profile-rustflags"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option for more information about the status of this feature. + +"#]]) + .run(); + + Package::new("bar", "1.0.0").publish(); + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = "1.0" + + [profile.dev.package.bar] + rustflags = ["-C", "link-dead-code=yes"] + "#, + ); + p.cargo("check") + .masquerade_as_nightly_cargo(&["profile-rustflags"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `profile-rustflags` is required + + The package requires the Cargo feature called `profile-rustflags`, but that feature is not stabilized in this version of Cargo (1.[..]). + Consider adding `cargo-features = ["profile-rustflags"]` to the top of Cargo.toml (above the [package] table) to tell Cargo you are opting in to use this unstable feature. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-rustflags-option for more information about the status of this feature. + +"#]]) + .run(); +} + +#[cargo_test] +fn debug_options_valid() { + let build = |option| { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + authors = [] + version = "0.0.0" + edition = "2015" + + [profile.dev] + debug = "{option}" + "# + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v") + }; + + for (option, cli) in [ + ("line-directives-only", "line-directives-only"), + ("line-tables-only", "line-tables-only"), + ("limited", "1"), + ("full", "2"), + ] { + build(option) + .with_stderr_data(&format!( + "\ +... +[RUNNING] `rustc [..]-C debuginfo={cli} [..]` +... +" + )) + .run(); + } + build("none") + .with_stderr_does_not_contain("[..]-C debuginfo[..]") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/progress.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/progress.rs new file mode 100644 index 000000000..5f9b8d2eb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/progress.rs @@ -0,0 +1,167 @@ +//! Tests for progress bar. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +#[cargo_test] +fn bad_progress_config_unknown_when() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + progress = { when = 'unknown' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `term.progress.when` + +Caused by: + unknown variant `unknown`, expected one of `auto`, `never`, `always` + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_progress_config_missing_width() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + progress = { when = 'always' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] "always" progress requires a `width` key + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_progress_config_missing_when() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + progress = { width = 1000 } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] error in [ROOT]/foo/.cargo/config.toml: could not load config key `term.progress` + +Caused by: + missing field `when` + +"#]]) + .run(); +} + +#[cargo_test] +fn always_shows_progress() { + const N: usize = 3; + let mut deps = String::new(); + for i in 1..=N { + Package::new(&format!("dep{}", i), "1.0.0").publish(); + deps.push_str(&format!("dep{} = \"1.0\"\n", i)); + } + + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + progress = { when = 'always', width = 100 } + "#, + ) + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + {} + "#, + deps + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data( + str![[r#" +[DOWNLOADING] [..] crate +[DOWNLOADED] 3 crates ([..]KB) in [..]s +[BUILDING] [..] [..]/4: [..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn never_progress() { + const N: usize = 3; + let mut deps = String::new(); + for i in 1..=N { + Package::new(&format!("dep{}", i), "1.0.0").publish(); + deps.push_str(&format!("dep{} = \"1.0\"\n", i)); + } + + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + progress = { when = 'never' } + "#, + ) + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + {} + "#, + deps + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_does_not_contain("[DOWNLOADING] [..] crates [..]") + .with_stderr_does_not_contain("[..][DOWNLOADED] 3 crates ([..]) in [..]") + .with_stderr_does_not_contain("[BUILDING] [..] [..]/4: [..]") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pub_priv.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pub_priv.rs new file mode 100644 index 000000000..b97698097 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/pub_priv.rs @@ -0,0 +1,684 @@ +//! Tests for public/private dependencies. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::str; + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn exported_priv_warning() { + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + priv_dep = "0.1.0" + "#, + ) + .file( + "src/lib.rs", + " + extern crate priv_dep; + pub fn use_priv(_: priv_dep::FromPriv) {} + ", + ) + .build(); + + p.cargo("check --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +... +src/lib.rs:3:13: [WARNING] type `FromPriv` from private dependency 'priv_dep' in public interface +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn exported_pub_dep() { + Package::new("pub_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPub;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + pub_dep = {version = "0.1.0", public = true} + "#, + ) + .file( + "src/lib.rs", + " + extern crate pub_dep; + pub fn use_pub(_: pub_dep::FromPub) {} + ", + ) + .build(); + + p.cargo("check --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] pub_dep v0.1.0 (registry `dummy-registry`) +[CHECKING] pub_dep v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +pub fn requires_nightly_cargo() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check --message-format=short") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the cargo feature `public-dependency` requires a nightly version of Cargo, but this is the `stable` channel + See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels. + See https://doc.rust-lang.org/[..]cargo/reference/unstable.html#public-dependency for more information about using this feature. + +"#]]) + .run(); +} + +#[cargo_test] +fn requires_feature() { + Package::new("pub_dep", "0.1.0") + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + pub_dep = { version = "0.1.0", public = true } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[WARNING] ignoring `public` on dependency pub_dep, pass `-Zpublic-dependency` to enable support for it +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] pub_dep v0.1.0 (registry `dummy-registry`) +[CHECKING] pub_dep v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn pub_dev_dependency() { + Package::new("pub_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPub;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dev-dependencies] + pub_dep = {version = "0.1.0", public = true} + "#, + ) + .file( + "src/lib.rs", + " + extern crate pub_dep; + pub fn use_pub(_: pub_dep::FromPub) {} + ", + ) + .build(); + + p.cargo("check --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + 'public' specifier can only be used on regular dependencies, not dev-dependencies + +"#]]) + .run(); +} + +#[cargo_test] +fn pub_dev_dependency_without_feature() { + Package::new("pub_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPub;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dev-dependencies] + pub_dep = {version = "0.1.0", public = true} + "#, + ) + .file( + "tests/mod.rs", + " + extern crate pub_dep; + pub fn use_pub(_: pub_dep::FromPub) {} + ", + ) + .build(); + + p.cargo("check --message-format=short") + .with_stderr_data(str![[r#" +[WARNING] 'public' specifier can only be used on regular dependencies, not dev-dependencies +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn workspace_pub_disallowed() { + Package::new("foo1", "0.1.0") + .file("src/lib.rs", "pub struct FromFoo;") + .publish(); + Package::new("foo2", "0.1.0") + .file("src/lib.rs", "pub struct FromFoo;") + .publish(); + Package::new("foo3", "0.1.0") + .file("src/lib.rs", "pub struct FromFoo;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [workspace.dependencies] + foo1 = "0.1.0" + foo2 = { version = "0.1.0", public = true } + foo3 = { version = "0.1.0", public = false } + + [dependencies] + foo1 = { workspace = true, public = true } + foo2 = { workspace = true } + foo3 = { workspace = true, public = true } + "#, + ) + .file( + "src/lib.rs", + " + #![deny(exported_private_dependencies)] + pub fn use_priv1(_: foo1::FromFoo) {} + pub fn use_priv2(_: foo2::FromFoo) {} + pub fn use_priv3(_: foo3::FromFoo) {} + ", + ) + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + foo2 is public, but workspace dependencies cannot be public + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn allow_priv_in_tests() { + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + priv_dep = {version = "0.1.0", public = false} + "#, + ) + .file( + "tests/mod.rs", + " + extern crate priv_dep; + pub fn use_priv(_: priv_dep::FromPriv) {} + ", + ) + .build(); + + p.cargo("check --tests --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`) +[CHECKING] priv_dep v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn allow_priv_in_benchs() { + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + priv_dep = {version = "0.1.0", public = false} + "#, + ) + .file( + "benches/mod.rs", + " + extern crate priv_dep; + pub fn use_priv(_: priv_dep::FromPriv) {} + ", + ) + .build(); + + p.cargo("check --benches --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`) +[CHECKING] priv_dep v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn allow_priv_in_bins() { + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + priv_dep = {version = "0.1.0", public = false} + "#, + ) + .file( + "src/main.rs", + " + extern crate priv_dep; + pub fn use_priv(_: priv_dep::FromPriv) {} + fn main() {} + ", + ) + .build(); + + p.cargo("check --bins --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`) +[CHECKING] priv_dep v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn allow_priv_in_examples() { + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + priv_dep = {version = "0.1.0", public = false} + "#, + ) + .file( + "examples/lib.rs", + " + extern crate priv_dep; + pub fn use_priv(_: priv_dep::FromPriv) {} + fn main() {} + ", + ) + .build(); + + p.cargo("check --examples --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`) +[CHECKING] priv_dep v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn allow_priv_in_custom_build() { + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [build-dependencies] + priv_dep = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "build.rs", + " + extern crate priv_dep; + pub fn use_priv(_: priv_dep::FromPriv) {} + fn main() {} + ", + ) + .build(); + + p.cargo("check --all-targets --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] priv_dep v0.1.0 (registry `dummy-registry`) +[COMPILING] priv_dep v0.1.0 +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn publish_package_with_public_dependency() { + Package::new("pub_bar", "0.1.0") + .file("src/lib.rs", "pub struct FromPub;") + .publish(); + Package::new("bar", "0.1.0") + .cargo_feature("public-dependency") + .add_dep(Dependency::new("pub_bar", "0.1.0").public(true)) + .file( + "src/lib.rs", + " + extern crate pub_bar; + pub use pub_bar::FromPub as BarFromPub; + ", + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + [dependencies] + bar = {version = "0.1.0", public = true} + "#, + ) + .file( + "src/lib.rs", + " + extern crate bar; + pub fn use_pub(_: bar::BarFromPub) {} + ", + ) + .build(); + + p.cargo("check --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] pub_bar v0.1.0 (registry `dummy-registry`) +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] pub_bar v0.1.0 +[CHECKING] bar v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn verify_mix_cargo_feature_z() { + Package::new("dep", "0.1.0") + .file("src/lib.rs", "pub struct FromDep;") + .publish(); + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + Package::new("pub_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPub;") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["public-dependency"] + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + dep = "0.1.0" + priv_dep = {version = "0.1.0", public = false} + pub_dep = {version = "0.1.0", public = true} + "#, + ) + .file( + "src/lib.rs", + " + extern crate dep; + extern crate priv_dep; + extern crate pub_dep; + pub fn use_dep(_: dep::FromDep) {} + pub fn use_priv(_: priv_dep::FromPriv) {} + pub fn use_pub(_: pub_dep::FromPub) {} + ", + ) + .build(); + + p.cargo("check -Zpublic-dependency --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data(str![[r#" +... +src/lib.rs:5:13: [WARNING] type `FromDep` from private dependency 'dep' in public interface +src/lib.rs:6:13: [WARNING] type `FromPriv` from private dependency 'priv_dep' in public interface +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")] +fn verify_z_public_dependency() { + Package::new("dep", "0.1.0") + .file("src/lib.rs", "pub struct FromDep;") + .publish(); + Package::new("priv_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPriv;") + .publish(); + Package::new("pub_dep", "0.1.0") + .file("src/lib.rs", "pub struct FromPub;") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + dep = "0.1.0" + priv_dep = {version = "0.1.0", public = false} + pub_dep = {version = "0.1.0", public = true} + "#, + ) + .file( + "src/lib.rs", + " + extern crate dep; + extern crate priv_dep; + extern crate pub_dep; + pub fn use_dep(_: dep::FromDep) {} + pub fn use_priv(_: priv_dep::FromPriv) {} + pub fn use_pub(_: pub_dep::FromPub) {} + ", + ) + .build(); + + p.cargo("check -Zpublic-dependency --message-format=short") + .masquerade_as_nightly_cargo(&["public-dependency"]) + .with_stderr_data( + str![[r#" +... +src/lib.rs:5:13: [WARNING] type `FromDep` from private dependency 'dep' in public interface +src/lib.rs:6:13: [WARNING] type `FromPriv` from private dependency 'priv_dep' in public interface +... +"#]] + .unordered(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish.rs new file mode 100644 index 000000000..e014a3436 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish.rs @@ -0,0 +1,4113 @@ +//! Tests for the `cargo publish` command. + +use std::fs; +use std::sync::{Arc, Mutex}; + +use cargo_test_support::git::{self, repo}; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package, RegistryBuilder, Response}; +use cargo_test_support::{basic_manifest, project, publish, str}; +use cargo_test_support::{paths, Project}; + +const CLEAN_FOO_JSON: &str = r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [], + "description": "foo", + "documentation": "foo", + "features": {}, + "homepage": "foo", + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": "foo", + "rust_version": null, + "vers": "0.0.1" + } +"#; + +fn validate_upload_foo() { + publish::validate_upload( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [], + "description": "foo", + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.0.1" + } + "#, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + ); +} + +fn validate_upload_li() { + publish::validate_upload( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [], + "description": "li", + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "li", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": "1.69", + "vers": "0.0.1" + } + "#, + "li-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + ); +} + +#[cargo_test] +fn simple() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + validate_upload_foo(); +} + +#[cargo_test] +fn duplicate_version() { + let registry_dupl = RegistryBuilder::new().http_api().http_index().build(); + Package::new("foo", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --dry-run") + .replace_crates_io(registry_dupl.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] crate foo@0.0.1 already exists on crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[WARNING] aborting upload due to dry run + +"#]]) + .run(); + + p.cargo("publish") + .replace_crates_io(registry_dupl.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] crate foo@0.0.1 already exists on crates.io index + +"#]]) + .run(); +} + +// Check that the `token` key works at the root instead of under a +// `[registry]` table. +#[cargo_test] +fn simple_publish_with_http() { + let _reg = registry::RegistryBuilder::new() + .http_api() + .token(registry::Token::Plaintext("sekrit".to_string())) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify --token sekrit --registry dummy-registry") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `dummy-registry` +[NOTE] waiting for `foo v0.0.1` to be available at registry `dummy-registry`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `dummy-registry` + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_publish_with_asymmetric() { + let _reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative_named("dummy-registry") + .token(registry::Token::rfc_key()) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify -Zasymmetric-token --registry dummy-registry") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `dummy-registry` +[NOTE] waiting for `foo v0.0.1` to be available at registry `dummy-registry`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `dummy-registry` + +"#]]) + .run(); +} + +#[cargo_test] +fn old_token_location() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + let credentials = paths::home().join(".cargo/credentials.toml"); + fs::remove_file(&credentials).unwrap(); + + // Verify can't publish without a token. + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] no token found, please run `cargo login` +or use environment variable CARGO_REGISTRY_TOKEN + +"#]]) + .run(); + + fs::write(&credentials, format!(r#"token = "{}""#, registry.token())).unwrap(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Skip `validate_upload_foo` as we just cared we got far enough for verify the token behavior. + // Other tests will verify the endpoint gets the right payload. +} + +#[cargo_test] +fn simple_with_index() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify") + .arg("--token") + .arg(registry.token()) + .arg("--index") + .arg(registry.index_url().as_str()) + .with_stderr_data(str![[r#" +[UPDATING] `[ROOT]/registry` index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `[ROOT]/registry` +[NOTE] waiting for `foo v0.0.1` to be available at registry `[ROOT]/registry`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `[ROOT]/registry` + +"#]]) + .run(); + + // Skip `validate_upload_foo` as we just cared we got far enough for verify the VCS behavior. + // Other tests will verify the endpoint gets the right payload. +} + +#[cargo_test] +fn git_deps() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies.foo] + git = "git://path/to/nowhere" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] all dependencies must have a version specified when publishing. +dependency `foo` does not specify a version +Note: The published dependency will use the version from crates.io, +the `git` specification will be removed from the dependency declaration. + +"#]]) + .run(); +} + +#[cargo_test] +fn path_dependency_no_version() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] all dependencies must have a version specified when publishing. +dependency `bar` does not specify a version +Note: The published dependency will use the version from crates.io, +the `path` specification will be removed from the dependency declaration. + +"#]]) + .run(); +} + +#[cargo_test] +fn unpublishable_crate() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + publish = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --index") + .arg(registry.index_url().as_str()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `foo` cannot be published. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. + +"#]]) + .run(); +} + +#[cargo_test] +fn dont_publish_dirty() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project().file("bar", "").build(); + + let _ = git::repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] 1 files in the working directory contain changes that were not yet committed into git: + +bar + +to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_clean() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project().build(); + + let _ = repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Skip `validate_upload_foo_clean` as we just cared we got far enough for verify the VCS behavior. + // Other tests will verify the endpoint gets the right payload. +} + +#[cargo_test] +fn publish_in_sub_repo() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project().no_manifest().file("baz", "").build(); + + let _ = repo(&paths::root().join("foo")) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .cwd("bar") + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.0.1 ([ROOT]/foo/bar) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo/bar/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo/bar) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Skip `validate_upload_foo_clean` as we just cared we got far enough for verify the VCS behavior. + // Other tests will verify the endpoint gets the right payload. +} + +#[cargo_test] +fn publish_when_ignored() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project().file("baz", "").build(); + + let _ = repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file(".gitignore", "baz") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Skip `validate_upload` as we just cared we got far enough for verify the VCS behavior. + // Other tests will verify the endpoint gets the right payload. +} + +#[cargo_test] +fn ignore_when_crate_ignored() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project().no_manifest().file("bar/baz", "").build(); + + let _ = repo(&paths::root().join("foo")) + .file(".gitignore", "bar") + .nocommit_file( + "bar/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .nocommit_file("bar/src/main.rs", "fn main() {}"); + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .cwd("bar") + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.0.1 ([ROOT]/foo/bar) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo/bar/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo/bar) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Skip `validate_upload` as we just cared we got far enough for verify the VCS behavior. + // Other tests will verify the endpoint gets the right payload. +} + +#[cargo_test] +fn new_crate_rejected() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project().file("baz", "").build(); + + let _ = repo(&paths::root().join("foo")) + .nocommit_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .nocommit_file("src/main.rs", "fn main() {}"); + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] 3 files in the working directory contain changes that were not yet committed into git: +... +"#]]) + .run(); +} + +#[cargo_test] +fn dry_run() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --dry-run --index") + .arg(registry.index_url().as_str()) + .with_stderr_data(str![[r#" +[UPDATING] `[ROOT]/registry` index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[WARNING] aborting upload due to dry run + +"#]]) + .run(); + + // Ensure the API request wasn't actually made + assert!(registry::api_path().join("api/v1/crates").exists()); + assert!(!registry::api_path().join("api/v1/crates/new").exists()); +} + +#[cargo_test] +fn registry_not_in_publish_list() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + publish = [ + "test" + ] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .arg("--registry") + .arg("alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `foo` cannot be published. +The registry `alternative` is not listed in the `package.publish` value in Cargo.toml. + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_empty_list() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + publish = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `foo` cannot be published. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_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" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + publish = ["alternative"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --registry alternative") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `alternative` +[NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` + +"#]]) + .run(); + + publish::validate_alt_upload( + CLEAN_FOO_JSON, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + ".cargo_vcs_info.json", + ], + ); +} + +#[cargo_test] +fn publish_implicitly_to_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" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + publish = ["alternative"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .with_stderr_data(str![[r#" +[NOTE] found `alternative` as only allowed registry. Publishing to it automatically. +[UPDATING] `alternative` index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `alternative` +[NOTE] waiting for `foo v0.0.1` to be available at registry `alternative`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `alternative` + +"#]]) + .run(); + + publish::validate_alt_upload( + CLEAN_FOO_JSON, + "foo-0.0.1.crate", + &[ + "Cargo.lock", + "Cargo.toml", + "Cargo.toml.orig", + "src/main.rs", + ".cargo_vcs_info.json", + ], + ); +} + +#[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" + edition = "2015" + 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_data(str![[r#" +[ERROR] command-line argument --index requires --token to be specified + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_fail_with_no_registry_specified() { + let p = project().build(); + + let _ = repo(&paths::root().join("foo")) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + publish = ["alternative", "test"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] --registry is required to disambiguate between "alternative" or "test" registries + +"#]]) + .run(); +} + +#[cargo_test] +fn block_publish_no_registry() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + publish = [] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `foo` cannot be published. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. + +"#]]) + .run(); +} + +// Explicitly setting `crates-io` in the publish list. +#[cargo_test] +fn publish_with_crates_io_explicit() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + publish = ["crates-io"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `foo` cannot be published. +The registry `alternative` is not listed in the `package.publish` value in Cargo.toml. + +"#]]) + .run(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_with_select_features() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("publish --features required") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_with_all_features() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [features] + required = [] + optional = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("publish --all-features") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_with_no_default_features() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [features] + default = ["required"] + required = [] + "#, + ) + .file( + "src/main.rs", + "#[cfg(not(feature = \"required\"))] + compile_error!(\"This crate requires `required` feature!\"); + fn main() {}", + ) + .build(); + + p.cargo("publish --no-default-features") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] This crate requires `required` feature! +... +"#]]) + .run(); +} + +#[cargo_test] +fn publish_with_patch() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + Package::new("bar", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + [dependencies] + bar = "1.0" + [patch.crates-io] + bar = { path = "bar" } + "#, + ) + .file( + "src/main.rs", + "extern crate bar; + fn main() { + bar::newfunc(); + }", + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "1.0.0")) + .file("bar/src/lib.rs", "pub fn newfunc() {}") + .build(); + + // Check that it works with the patched crate. + p.cargo("build").run(); + + // Check that verify fails with patched crate which has new functionality. + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +... +error[E0425]: cannot find function `newfunc` in crate `bar` +... +"#]]) + .run(); + + // Remove the usage of new functionality and try again. + p.change_file("src/main.rs", "extern crate bar; pub fn main() {}"); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] bar v1.0.0 +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "bar", + "optional": false, + "target": null, + "version_req": "^1.0" + } + ], + "description": "foo", + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.0.1" + } + "#, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + ); +} + +#[cargo_test] +fn publish_checks_for_token_before_verify() { + let registry = registry::RegistryBuilder::new() + .no_configure_token() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // Assert upload token error before the package is verified + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] no token found, please run `cargo login` +or use environment variable CARGO_REGISTRY_TOKEN + +"#]]) + .with_stderr_does_not_contain("[VERIFYING] foo v0.0.1 ([CWD])") + .run(); + + // Assert package verified successfully on dry run + p.cargo("publish --dry-run") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[WARNING] aborting upload due to dry run + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_with_bad_source() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [source.crates-io] + replace-with = 'local-registry' + + [source.local-registry] + local-registry = 'registry' + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] crates-io is replaced with non-remote-registry source registry `[ROOT]/foo/registry`; +include `--registry crates-io` to use crates.io + +"#]]) + .run(); + + p.change_file( + ".cargo/config.toml", + r#" + [source.crates-io] + replace-with = "vendored-sources" + + [source.vendored-sources] + directory = "vendor" + "#, + ); + + p.cargo("publish") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] crates-io is replaced with non-remote-registry source dir [ROOT]/foo/vendor; +include `--registry crates-io` to use crates.io + +"#]]) + .run(); +} + +// A dependency with both `git` and `version`. +#[cargo_test] +fn publish_git_with_version() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + Package::new("dep1", "1.0.1") + .file("src/lib.rs", "pub fn f() -> i32 {1}") + .publish(); + + let git_project = git::new("dep1", |project| { + project + .file("Cargo.toml", &basic_manifest("dep1", "1.0.0")) + .file("src/lib.rs", "pub fn f() -> i32 {2}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + edition = "2018" + license = "MIT" + description = "foo" + + [dependencies] + dep1 = {{version = "1.0", git="{}"}} + "#, + git_project.url() + ), + ) + .file( + "src/main.rs", + r#" + pub fn main() { + println!("{}", dep1::f()); + } + "#, + ) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +2 + +"#]]) + .run(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +[UPLOADED] foo v0.1.0 to registry `crates-io` +[NOTE] waiting for `foo v0.1.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.1.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "dep1", + "optional": false, + "target": null, + "version_req": "^1.0" + } + ], + "description": "foo", + "documentation": null, + "features": {}, + "homepage": null, + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.1.0" + } + "#, + "foo-0.1.0.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [ + ( + "Cargo.toml", + // Check that only `version` is included in Cargo.toml. + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "foo" +version = "0.1.0" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +readme = false +license = "MIT" + +[[bin]] +name = "foo" +path = "src/main.rs" + +[dependencies.dep1] +version = "1.0" + +"##]], + ), + ( + "Cargo.lock", + // The important check here is that it is 1.0.1 in the registry. + str![[r##" +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "dep1" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "[..]" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "dep1", +] + +"##]], + ), + ], + ); +} + +#[cargo_test] +fn publish_dev_dep_stripping() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + Package::new("normal-only", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("optional-dep-feature", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("optional-namespaced", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("optional-renamed-dep-feature", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("optional-renamed-namespaced", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("build-only", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("normal-and-dev", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("target-normal-only", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("target-build-only", "1.0.0") + .feature("cat", &[]) + .publish(); + Package::new("target-normal-and-dev", "1.0.0") + .feature("cat", &[]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + + + [features] + foo_feature = [ + "normal-only/cat", + "build-only/cat", + "dev-only/cat", + "renamed-dev-only01/cat", + "normal-and-dev/cat", + "target-normal-only/cat", + "target-build-only/cat", + "target-dev-only/cat", + "target-normal-and-dev/cat", + "optional-dep-feature/cat", + "dep:optional-namespaced", + "optional-renamed-dep-feature10/cat", + "dep:optional-renamed-namespaced10", + ] + + [dependencies] + normal-only = { version = "1.0", features = ["cat"] } + normal-and-dev = { version = "1.0", features = ["cat"] } + optional-dep-feature = { version = "1.0", features = ["cat"], optional = true } + optional-namespaced = { version = "1.0", features = ["cat"], optional = true } + optional-renamed-dep-feature10 = { version = "1.0", features = ["cat"], optional = true, package = "optional-renamed-dep-feature" } + optional-renamed-namespaced10 = { version = "1.0", features = ["cat"], optional = true, package = "optional-renamed-namespaced" } + + [build-dependencies] + build-only = { version = "1.0", features = ["cat"] } + + [dev-dependencies] + dev-only = { path = "../dev-only", features = ["cat"] } + renamed-dev-only01 = { path = "../renamed-dev-only", features = ["cat"], package = "renamed-dev-only" } + normal-and-dev = { version = "1.0", features = ["cat"] } + + [target.'cfg(unix)'.dependencies] + target-normal-only = { version = "1.0", features = ["cat"] } + target-normal-and-dev = { version = "1.0", features = ["cat"] } + + [target.'cfg(unix)'.build-dependencies] + target-build-only = { version = "1.0", features = ["cat"] } + + [target.'cfg(unix)'.dev-dependencies] + target-dev-only = { path = "../dev-only", features = ["cat"] } + target-normal-and-dev = { version = "1.0", features = ["cat"] } + "#, + ) + .file("src/main.rs", "") + .file( + "dev-only/Cargo.toml", + r#" + [package] + name = "dev-only" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + cat = [] + "#, + ) + .file( + "dev-only/src/lib.rs", + r#" + #[cfg(feature = "cat")] + pub fn cat() {} + "#, + ) + .file( + "renamed-dev-only/Cargo.toml", + r#" + [package] + name = "renamed-dev-only" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + cat = [] + "#, + ) + .file( + "renamed-dev-only/src/lib.rs", + r#" + #[cfg(feature = "cat")] + pub fn cat() {} + "#, + ) + .build(); + + p.cargo("publish --no-verify") + .env("RUSTFLAGS", "--cfg unix") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +[UPLOADED] foo v0.1.0 to registry `crates-io` +[NOTE] waiting for `foo v0.1.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.1.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "normal-and-dev", + "optional": false, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "normal-only", + "optional": false, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "optional-dep-feature", + "optional": true, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "optional-namespaced", + "optional": true, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "explicit_name_in_toml": "optional-renamed-dep-feature10", + "features": [ + "cat" + ], + "kind": "normal", + "name": "optional-renamed-dep-feature", + "optional": true, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "explicit_name_in_toml": "optional-renamed-namespaced10", + "features": [ + "cat" + ], + "kind": "normal", + "name": "optional-renamed-namespaced", + "optional": true, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "dev", + "name": "normal-and-dev", + "optional": false, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "build", + "name": "build-only", + "optional": false, + "target": null, + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "target-normal-and-dev", + "optional": false, + "target": "cfg(unix)", + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "normal", + "name": "target-normal-only", + "optional": false, + "target": "cfg(unix)", + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "build", + "name": "target-build-only", + "optional": false, + "target": "cfg(unix)", + "version_req": "^1.0" + }, + { + "default_features": true, + "features": [ + "cat" + ], + "kind": "dev", + "name": "target-normal-and-dev", + "optional": false, + "target": "cfg(unix)", + "version_req": "^1.0" + } + ], + "description": "foo", + "documentation": "foo", + "features": { + "foo_feature": [ + "normal-only/cat", + "build-only/cat", + "normal-and-dev/cat", + "target-normal-only/cat", + "target-build-only/cat", + "target-normal-and-dev/cat", + "optional-dep-feature/cat", + "dep:optional-namespaced", + "optional-renamed-dep-feature10/cat", + "dep:optional-renamed-namespaced10" + ] + }, + "homepage": "foo", + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": "foo", + "rust_version": null, + "vers": "0.1.0" + } + "#, + "foo-0.1.0.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.1.0" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "foo" +documentation = "foo" +readme = false +license = "MIT" +repository = "foo" + +[features] +foo_feature = [ + "normal-only/cat", + "build-only/cat", + "normal-and-dev/cat", + "target-normal-only/cat", + "target-build-only/cat", + "target-normal-and-dev/cat", + "optional-dep-feature/cat", + "dep:optional-namespaced", + "optional-renamed-dep-feature10/cat", + "dep:optional-renamed-namespaced10", +] + +[[bin]] +name = "foo" +path = "src/main.rs" + +[dependencies.normal-and-dev] +version = "1.0" +features = ["cat"] + +[dependencies.normal-only] +version = "1.0" +features = ["cat"] + +[dependencies.optional-dep-feature] +version = "1.0" +features = ["cat"] +optional = true + +[dependencies.optional-namespaced] +version = "1.0" +features = ["cat"] +optional = true + +[dependencies.optional-renamed-dep-feature10] +version = "1.0" +features = ["cat"] +optional = true +package = "optional-renamed-dep-feature" + +[dependencies.optional-renamed-namespaced10] +version = "1.0" +features = ["cat"] +optional = true +package = "optional-renamed-namespaced" + +[dev-dependencies.normal-and-dev] +version = "1.0" +features = ["cat"] + +[build-dependencies.build-only] +version = "1.0" +features = ["cat"] + +[target."cfg(unix)".dependencies.target-normal-and-dev] +version = "1.0" +features = ["cat"] + +[target."cfg(unix)".dependencies.target-normal-only] +version = "1.0" +features = ["cat"] + +[target."cfg(unix)".build-dependencies.target-build-only] +version = "1.0" +features = ["cat"] + +[target."cfg(unix)".dev-dependencies.target-normal-and-dev] +version = "1.0" +features = ["cat"] + +"##]], + )], + ); +} + +#[cargo_test] +fn credentials_ambiguous_filename() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + // Make token in `credentials.toml` incorrect to ensure it is not read. + let credentials_toml = paths::home().join(".cargo/credentials.toml"); + fs::write(credentials_toml, r#"token = "wrong-token""#).unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +... + Unauthorized message from server. + +"#]]) + .run(); + + // Favor `credentials` if exists. + let credentials = paths::home().join(".cargo/credentials"); + fs::write(credentials, r#"token = "sekrit""#).unwrap(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] both `[ROOT]/home/.cargo/credentials` and `[ROOT]/home/.cargo/credentials.toml` exist. Using `[ROOT]/home/.cargo/credentials` +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +// --index will not load registry.token to avoid possibly leaking +// crates.io token to another server. +#[cargo_test] +fn index_requires_token() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let credentials = paths::home().join(".cargo/credentials.toml"); + fs::remove_file(&credentials).unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --index") + .arg(registry.index_url().as_str()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] command-line argument --index requires --token to be specified + +"#]]) + .run(); +} + +// publish with source replacement without --registry +#[cargo_test] +fn cratesio_source_replacement() { + registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] crates-io is replaced with remote registry dummy-registry; +include `--registry dummy-registry` or `--registry crates-io` + +"#]]) + .run(); +} + +// Registry returns an API error. +#[cargo_test] +fn api_error_json() { + let _registry = registry::RegistryBuilder::new() + .alternative() + .http_api() + .add_responder("/api/v1/crates/new", |_, _| Response { + body: br#"{"errors": [{"detail": "you must be logged in"}]}"#.to_vec(), + code: 403, + headers: vec![], + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to publish to registry at http://127.0.0.1:[..]/ + +Caused by: + the remote server responded with an error (status 403 Forbidden): you must be logged in + +"#]]) + .run(); +} + +// Registry returns an API error with a 200 status code. +#[cargo_test] +fn api_error_200() { + let _registry = registry::RegistryBuilder::new() + .alternative() + .http_api() + .add_responder("/api/v1/crates/new", |_, _| Response { + body: br#"{"errors": [{"detail": "max upload size is 123"}]}"#.to_vec(), + code: 200, + headers: vec![], + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to publish to registry at http://127.0.0.1:[..]/ + +Caused by: + the remote server responded with an [ERROR] max upload size is 123 + +"#]]) + .run(); +} + +// Registry returns an error code without a JSON message. +#[cargo_test] +fn api_error_code() { + let _registry = registry::RegistryBuilder::new() + .alternative() + .http_api() + .add_responder("/api/v1/crates/new", |_, _| Response { + body: br#"go away"#.to_vec(), + code: 400, + headers: vec![], + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to publish to registry at http://127.0.0.1:[..]/ + +Caused by: + failed to get a 200 OK response, got 400 + headers: + HTTP/1.1 400 + Content-Length: 7 + Connection: close + + body: + go away + +"#]]) + .run(); +} + +// Registry has a network error. +#[cargo_test] +fn api_curl_error() { + let _registry = registry::RegistryBuilder::new() + .alternative() + .http_api() + .add_responder("/api/v1/crates/new", |_, _| { + panic!("broke"); + }) + .build(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // This doesn't check for the exact text of the error in the remote + // possibility that cargo is linked with a weird version of libcurl, or + // curl changes the text of the message. Currently the message 52 + // (CURLE_GOT_NOTHING) is: + // Server returned nothing (no headers, no data) (Empty reply from server) + p.cargo("publish --no-verify --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to publish to registry at http://127.0.0.1:[..]/ + +Caused by: + [52] Server returned nothing (no headers, no data) (Empty reply from server) + +"#]]) + .run(); +} + +// Registry returns an invalid response. +#[cargo_test] +fn api_other_error() { + let _registry = registry::RegistryBuilder::new() + .alternative() + .http_api() + .add_responder("/api/v1/crates/new", |_, _| Response { + body: b"\xff".to_vec(), + code: 200, + headers: vec![], + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --registry alternative") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to publish to registry at http://127.0.0.1:[..]/ + +Caused by: + invalid response body from server + +Caused by: + invalid utf-8 sequence of 1 bytes from index 0 + +"#]]) + .run(); +} + +#[cargo_test] +fn in_package_workspace() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + [workspace] + members = ["li"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "li/Cargo.toml", + r#" + [package] + name = "li" + version = "0.0.1" + edition = "2015" + rust-version = "1.69" + description = "li" + license = "MIT" + "#, + ) + .file("li/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish -p li --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] li v0.0.1 ([ROOT]/foo/li) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] li v0.0.1 ([ROOT]/foo/li) +[UPLOADED] li v0.0.1 to registry `crates-io` +[NOTE] waiting for `li v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] li v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + validate_upload_li(); +} + +#[cargo_test] +fn with_duplicate_spec_in_members() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [workspace] + resolver = "2" + members = ["li","bar"] + default-members = ["li","bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "li/Cargo.toml", + r#" + [package] + name = "li" + version = "0.0.1" + edition = "2015" + description = "li" + license = "MIT" + "#, + ) + .file("li/src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + description = "bar" + license = "MIT" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `-p` argument must be specified to select a single package to publish + +"#]]) + .run(); +} + +#[cargo_test] +fn in_package_workspace_with_members_with_features_old() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + [workspace] + members = ["li"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "li/Cargo.toml", + r#" + [package] + name = "li" + version = "0.0.1" + edition = "2015" + rust-version = "1.69" + description = "li" + license = "MIT" + "#, + ) + .file("li/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish -p li --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] li v0.0.1 ([ROOT]/foo/li) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] li v0.0.1 ([ROOT]/foo/li) +[UPLOADED] li v0.0.1 to registry `crates-io` +[NOTE] waiting for `li v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] li v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + validate_upload_li(); +} + +#[cargo_test] +fn in_virtual_workspace() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("foo/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `-p` argument must be specified in the root of a virtual workspace + +"#]]) + .run(); +} + +#[cargo_test] +fn in_virtual_workspace_with_p() { + // `publish` generally requires a remote registry + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo","li"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("foo/src/main.rs", "fn main() {}") + .file( + "li/Cargo.toml", + r#" + [package] + name = "li" + version = "0.0.1" + edition = "2015" + rust-version = "1.69" + description = "li" + license = "MIT" + "#, + ) + .file("li/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish -p li --no-verify") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] li v0.0.1 ([ROOT]/foo/li) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] li v0.0.1 ([ROOT]/foo/li) +[UPLOADED] li v0.0.1 to registry `crates-io` +[NOTE] waiting for `li v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] li v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn in_package_workspace_not_found() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "li/Cargo.toml", + r#" + [package] + name = "li" + version = "0.0.1" + edition = "2021" + authors = [] + license = "MIT" + description = "li" + "#, + ) + .file("li/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish -p li --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `li` did not match any packages + +[HELP] a package with a similar name exists: `foo` + +"#]]) + .run(); +} + +#[cargo_test] +fn in_package_workspace_found_multiple() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + [workspace] + members = ["li","lii"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "li/Cargo.toml", + r#" + [package] + name = "li" + version = "0.0.1" + edition = "2021" + authors = [] + license = "MIT" + description = "li" + "#, + ) + .file("li/src/main.rs", "fn main() {}") + .file( + "lii/Cargo.toml", + r#" + [package] + name = "lii" + version = "0.0.1" + edition = "2021" + authors = [] + license = "MIT" + description = "lii" + "#, + ) + .file("lii/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish -p li* --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `-p` argument must be specified to select a single package to publish + +"#]]) + .run(); +} + +#[cargo_test] +// https://github.com/rust-lang/cargo/issues/10536 +fn publish_path_dependency_without_workspace() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2021" + authors = [] + license = "MIT" + description = "bar" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish -p bar --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package ID specification `bar` did not match any packages + +[HELP] a package with a similar name exists: `foo` + +"#]]) + .run(); +} + +#[cargo_test] +fn http_api_not_noop() { + let registry = registry::RegistryBuilder::new().http_api().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies] + foo = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); +} + +#[cargo_test] +fn wait_for_first_publish() { + // Counter for number of tries before the package is "published" + let arc: Arc> = Arc::new(Mutex::new(0)); + let arc2 = arc.clone(); + + // Registry returns an invalid response. + let registry = registry::RegistryBuilder::new() + .http_index() + .http_api() + .add_responder("/index/de/la/delay", move |req, server| { + let mut lock = arc.lock().unwrap(); + *lock += 1; + if *lock <= 1 { + server.not_found(req) + } else { + server.index(req) + } + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "delay" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(0) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] delay v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] delay v0.0.1 ([ROOT]/foo) +[UPLOADED] delay v0.0.1 to registry `crates-io` +[NOTE] waiting for `delay v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Verify the responder has been pinged + let lock = arc2.lock().unwrap(); + assert_eq!(*lock, 2); + drop(lock); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + delay = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build").with_status(0).run(); +} + +/// A separate test is needed for package names with - or _ as they hit +/// the responder twice per cargo invocation. If that ever gets changed +/// this test will need to be changed accordingly. +#[cargo_test] +fn wait_for_first_publish_underscore() { + // Counter for number of tries before the package is "published" + let arc: Arc> = Arc::new(Mutex::new(0)); + let arc2 = arc.clone(); + let misses = Arc::new(Mutex::new(Vec::new())); + let misses2 = misses.clone(); + + // Registry returns an invalid response. + let registry = registry::RegistryBuilder::new() + .http_index() + .http_api() + .add_responder("/index/de/la/delay_with_underscore", move |req, server| { + let mut lock = arc.lock().unwrap(); + *lock += 1; + if *lock <= 1 { + server.not_found(req) + } else { + server.index(req) + } + }) + .not_found_handler(move |req, _| { + misses.lock().unwrap().push(req.url.to_string()); + Response { + body: b"not found".to_vec(), + code: 404, + headers: vec![], + } + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "delay_with_underscore" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(0) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] delay_with_underscore v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] delay_with_underscore v0.0.1 ([ROOT]/foo) +[UPLOADED] delay_with_underscore v0.0.1 to registry `crates-io` +[NOTE] waiting for `delay_with_underscore v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay_with_underscore v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Verify the repsponder has been pinged + let lock = arc2.lock().unwrap(); + assert_eq!(*lock, 2); + drop(lock); + { + let misses = misses2.lock().unwrap(); + assert!( + misses.len() == 1, + "should only have 1 not found URL; instead found {misses:?}" + ); + } + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + delay_with_underscore = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build").with_status(0).run(); +} + +#[cargo_test] +fn wait_for_subsequent_publish() { + // Counter for number of tries before the package is "published" + let arc: Arc> = Arc::new(Mutex::new(0)); + let arc2 = arc.clone(); + let publish_req = Arc::new(Mutex::new(None)); + let publish_req2 = publish_req.clone(); + + let registry = registry::RegistryBuilder::new() + .http_index() + .http_api() + .add_responder("/api/v1/crates/new", move |req, server| { + // Capture the publish request, but defer publishing + *publish_req.lock().unwrap() = Some(req.clone()); + server.ok(req) + }) + .add_responder("/index/de/la/delay", move |req, server| { + let mut lock = arc.lock().unwrap(); + *lock += 1; + if *lock == 3 { + // Run the publish on the 3rd attempt + let rep = server + .check_authorized_publish(&publish_req2.lock().unwrap().as_ref().unwrap()); + assert_eq!(rep.code, 200); + } + server.index(req) + }) + .build(); + + // Publish an earlier version + Package::new("delay", "0.0.1") + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "delay" + version = "0.0.2" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(0) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] delay v0.0.2 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] delay v0.0.2 ([ROOT]/foo) +[UPLOADED] delay v0.0.2 to registry `crates-io` +[NOTE] waiting for `delay v0.0.2` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay v0.0.2 at registry `crates-io` + +"#]]) + .run(); + + // Verify the responder has been pinged + let lock = arc2.lock().unwrap(); + assert_eq!(*lock, 3); + drop(lock); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + delay = "0.0.2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").with_status(0).run(); +} + +#[cargo_test] +fn skip_wait_for_publish() { + // Intentionally using local registry so the crate never makes it to the index + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + " + [publish] + timeout = 0 + ", + ) + .build(); + + p.cargo("publish --no-verify -Zpublish-timeout") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["publish-timeout"]) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn timeout_waiting_for_publish() { + // Publish doesn't happen within the timeout window. + let registry = registry::RegistryBuilder::new() + .http_api() + .delayed_index_update(20) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "delay" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [publish] + timeout = 2 + "#, + ) + .build(); + + p.cargo("publish --no-verify -Zpublish-timeout") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["publish-timeout"]) + .with_status(0) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] delay v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] delay v0.0.1 ([ROOT]/foo) +[UPLOADED] delay v0.0.1 to registry `crates-io` +[NOTE] waiting for `delay v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[WARNING] timed out waiting for `delay v0.0.1` to be available in registry `crates-io` +[NOTE] the registry may have a backlog that is delaying making the crate available. The crate should be available soon. + +"#]]) + .run(); +} + +#[cargo_test] +fn timeout_waiting_for_dependency_publish() { + // Publish doesn't happen within the timeout window. + let registry = registry::RegistryBuilder::new() + .http_api() + .delayed_index_update(20) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["main", "other", "dep"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies] + dep = { version = "0.0.1", path = "../dep" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "other/Cargo.toml", + r#" + [package] + name = "other" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies] + dep = { version = "0.0.1", path = "../dep" } + "#, + ) + .file("other/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("dep/src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [publish] + timeout = 2 + "#, + ) + .build(); + + p.cargo("publish --no-verify -Zpublish-timeout -Zpackage-workspace") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["publish-timeout", "package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] dep v0.0.1 ([ROOT]/foo/dep) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] main v0.0.1 ([ROOT]/foo/main) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] other v0.0.1 ([ROOT]/foo/other) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] dep v0.0.1 ([ROOT]/foo/dep) +[UPLOADED] dep v0.0.1 to registry `crates-io` +[NOTE] waiting for `dep v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[WARNING] timed out waiting for `dep v0.0.1` to be available in registry `crates-io` +[NOTE] the registry may have a backlog that is delaying making the crate available. The crate should be available soon. +[ERROR] unable to publish `main v0.0.1` and `other v0.0.1` due to time out while waiting for published dependencies to be available. + +"#]]) + .run(); +} + +#[cargo_test] +fn package_selection() { + let registry = registry::RegistryBuilder::new().http_api().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "#[test] fn a() {}") + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file("b/src/lib.rs", "#[test] fn b() {}") + .build(); + + p.cargo("publish --no-verify --dry-run -Zpackage-workspace --workspace") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] a v0.1.0 ([ROOT]/foo/a) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] b v0.1.0 ([ROOT]/foo/b) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] a v0.1.0 ([ROOT]/foo/a) +[WARNING] aborting upload due to dry run +[UPLOADING] b v0.1.0 ([ROOT]/foo/b) +[WARNING] aborting upload due to dry run + +"#]]) + .with_stdout_data(str![[r#""#]]) + .run(); + + p.cargo("publish --no-verify --dry-run -Zpackage-workspace --package a --package b") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] a v0.1.0 ([ROOT]/foo/a) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] b v0.1.0 ([ROOT]/foo/b) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] a v0.1.0 ([ROOT]/foo/a) +[WARNING] aborting upload due to dry run +[UPLOADING] b v0.1.0 ([ROOT]/foo/b) +[WARNING] aborting upload due to dry run + +"#]]) + .with_stdout_data(str![[r#""#]]) + .run(); + + p.cargo("publish --no-verify --dry-run -Zpackage-workspace --workspace --exclude b") + .replace_crates_io(registry.index_url()) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no description, license, license-file, documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] a v0.1.0 ([ROOT]/foo/a) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] a v0.1.0 ([ROOT]/foo/a) +[WARNING] aborting upload due to dry run + +"#]]) + .with_stdout_data(str![[r#""#]]) + .run(); + + p.cargo("publish --no-verify --dry-run --package a --package b") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `--package (multiple occurrences)` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels. +See https://github.com/rust-lang/cargo/issues/10948 for more information about the `--package (multiple occurrences)` flag. + +"#]]) + .with_stdout_data(str![[r#""#]]) + .run(); + + p.cargo("publish --no-verify --dry-run --workspace") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `--workspace` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels. +See https://github.com/rust-lang/cargo/issues/10948 for more information about the `--workspace` flag. + +"#]]) + .with_stdout_data(str![[r#""#]]) + .run(); + + p.cargo("publish --no-verify --dry-run --exclude b") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `--exclude` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels. +See https://github.com/rust-lang/cargo/issues/10948 for more information about the `--exclude` flag. + +"#]]) + .with_stdout_data(str![[r#""#]]) + .run(); +} + +#[cargo_test] +fn wait_for_git_publish() { + // Slow publish to an index with a git index. + let registry = registry::RegistryBuilder::new() + .http_api() + .delayed_index_update(5) + .build(); + + // Publish an earlier version + Package::new("delay", "0.0.1") + .file("src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "delay" + version = "0.0.2" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .with_status(0) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] delay v0.0.2 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] delay v0.0.2 ([ROOT]/foo) +[UPLOADED] delay v0.0.2 to registry `crates-io` +[NOTE] waiting for `delay v0.0.2` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] delay v0.0.2 at registry `crates-io` + +"#]]) + .run(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + [dependencies] + delay = "0.0.2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").with_status(0).run(); +} + +#[cargo_test] +fn invalid_token() { + // Checks publish behavior with an invalid token. + let registry = RegistryBuilder::new().http_api().http_index().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("publish --no-verify") + .replace_crates_io(registry.index_url()) + .env("CARGO_REGISTRY_TOKEN", "\x16") + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to publish to registry at http://127.0.0.1:[..]/ + +Caused by: + token contains invalid characters. + Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn versionless_package() { + // Use local registry for faster test times since no publish will occur + let registry = registry::init(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + description = "foo" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `foo` cannot be published. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. + +"#]]) + .run(); +} + +// A workspace with three projects that depend on one another (level1 -> level2 -> level3). +// level1 is a binary package, to test lockfile generation. +fn workspace_with_local_deps_project() -> Project { + project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["level1", "level2", "level3"] + + [workspace.dependencies] + level2 = { path = "level2", version = "0.0.1" } + "# + ) + .file( + "level1/Cargo.toml", + r#" + [package] + name = "level1" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level1" + repository = "bar" + + [dependencies] + # Let one dependency also specify features, for the added test coverage when generating package files. + level2 = { workspace = true, features = ["foo"] } + "#, + ) + .file("level1/src/main.rs", "fn main() {}") + .file( + "level2/Cargo.toml", + r#" + [package] + name = "level2" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level2" + repository = "bar" + + [features] + foo = [] + + [dependencies] + level3 = { path = "../level3", version = "0.0.1" } + "# + ) + .file("level2/src/lib.rs", "") + .file( + "level3/Cargo.toml", + r#" + [package] + name = "level3" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "level3" + repository = "bar" + "#, + ) + .file("level3/src/lib.rs", "") + .build() +} + +#[cargo_test] +fn workspace_with_local_deps() { + let crates_io = registry::init(); + let p = workspace_with_local_deps_project(); + + p.cargo("publish") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `-p` argument must be specified to select a single package to publish + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_with_local_deps_nightly() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + let p = workspace_with_local_deps_project(); + + p.cargo("publish -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] level3 v0.0.1 ([ROOT]/foo/level3) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level2 v0.0.1 ([ROOT]/foo/level2) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] level3 v0.0.1 ([ROOT]/foo/level3) +[COMPILING] level3 v0.0.1 ([ROOT]/foo/target/package/level3-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] level2 v0.0.1 ([ROOT]/foo/level2) +[UPDATING] crates.io index +[UNPACKING] level3 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] level3 v0.0.1 +[COMPILING] level2 v0.0.1 ([ROOT]/foo/target/package/level2-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPDATING] crates.io index +[UNPACKING] level2 v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] level3 v0.0.1 +[COMPILING] level2 v0.0.1 +[COMPILING] level1 v0.0.1 ([ROOT]/foo/target/package/level1-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] level3 v0.0.1 ([ROOT]/foo/level3) +[UPLOADED] level3 v0.0.1 to registry `crates-io` +[NOTE] waiting for `level3 v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] level3 v0.0.1 at registry `crates-io` +[UPLOADING] level2 v0.0.1 ([ROOT]/foo/level2) +[UPLOADED] level2 v0.0.1 to registry `crates-io` +[NOTE] waiting for `level2 v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] level2 v0.0.1 at registry `crates-io` +[UPLOADING] level1 v0.0.1 ([ROOT]/foo/level1) +[UPLOADED] level1 v0.0.1 to registry `crates-io` +[NOTE] waiting for `level1 v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] level1 v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_parallel() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b", "c"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "a" + repository = "bar" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "b" + repository = "bar" + "#, + ) + .file("b/src/lib.rs", "") + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "c" + repository = "bar" + + [dependencies] + a = { path = "../a", version = "0.0.1" } + b = { path = "../b", version = "0.0.1" } + "#, + ) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("publish -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(registry.index_url()) + .with_stderr_data( + str![[r#" +[UPDATING] crates.io index +[PACKAGING] a v0.0.1 ([ROOT]/foo/a) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] b v0.0.1 ([ROOT]/foo/b) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[PACKAGING] c v0.0.1 ([ROOT]/foo/c) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] a v0.0.1 ([ROOT]/foo/a) +[COMPILING] a v0.0.1 ([ROOT]/foo/target/package/a-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] b v0.0.1 ([ROOT]/foo/b) +[COMPILING] b v0.0.1 ([ROOT]/foo/target/package/b-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] c v0.0.1 ([ROOT]/foo/c) +[UPDATING] crates.io index +[UNPACKING] a v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[UNPACKING] b v0.0.1 (registry `[ROOT]/foo/target/package/tmp-registry`) +[COMPILING] a v0.0.1 +[COMPILING] b v0.0.1 +[COMPILING] c v0.0.1 ([ROOT]/foo/target/package/c-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADED] b v0.0.1 to registry `crates-io` +[UPLOADED] a v0.0.1 to registry `crates-io` +[NOTE] waiting for `a v0.0.1` or `b v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] a v0.0.1, b v0.0.1 at registry `crates-io` +[UPLOADING] c v0.0.1 ([ROOT]/foo/c) +[UPLOADED] c v0.0.1 to registry `crates-io` +[NOTE] waiting for `c v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] c v0.0.1 at registry `crates-io` +[UPLOADING] a v0.0.1 ([ROOT]/foo/a) +[UPLOADING] b v0.0.1 ([ROOT]/foo/b) +[UPDATING] crates.io index + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn workspace_missing_dependency() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "a" + repository = "bar" + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "b" + repository = "bar" + + [dependencies] + a = { path = "../a", version = "0.0.1" } + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("publish -Zpackage-workspace -p b") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] b v0.0.1 ([ROOT]/foo/b) +[UPDATING] crates.io index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `a` found + location searched: crates.io index + required by package `b v0.0.1 ([ROOT]/foo/b)` + +"#]]) + .run(); + + p.cargo("publish -Zpackage-workspace -p a") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] a v0.0.1 ([ROOT]/foo/a) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] a v0.0.1 ([ROOT]/foo/a) +[COMPILING] a v0.0.1 ([ROOT]/foo/target/package/a-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] a v0.0.1 ([ROOT]/foo/a) +[UPLOADED] a v0.0.1 to registry `crates-io` +[NOTE] waiting for `a v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] a v0.0.1 at registry `crates-io` + +"#]]) + .run(); + + // Publishing the whole workspace now will fail, as `a` is already published. + p.cargo("publish -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] crate a@0.0.1 already exists on crates.io index + +"#]]) + .run(); +} + +#[cargo_test] +fn one_unpublishable_package() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = false + + [dependencies] + dep = { path = "../dep", version = "0.1.0", registry = "alternative" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = ["alternative"] + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("publish -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `main` cannot be published. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_unpublishable_package() { + let _alt_reg = registry::RegistryBuilder::new() + .http_api() + .http_index() + .alternative() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["dep", "main"] + "#, + ) + .file( + "main/Cargo.toml", + r#" + [package] + name = "main" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "main" + repository = "bar" + publish = false + + [dependencies] + dep = { path = "../dep", version = "0.1.0" } + "#, + ) + .file("main/src/main.rs", "fn main() {}") + .file( + "dep/Cargo.toml", + r#" + [package] + name = "dep" + version = "0.1.0" + edition = "2015" + authors = [] + license = "MIT" + description = "dep" + repository = "bar" + publish = false + "#, + ) + .file("dep/src/lib.rs", "") + .build(); + + p.cargo("publish -Zpackage-workspace") + .masquerade_as_nightly_cargo(&["package-workspace"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `dep`, `main` cannot be published. +`package.publish` must be set to `true` or a non-empty list in Cargo.toml to publish. + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish_lockfile.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish_lockfile.rs new file mode 100644 index 000000000..51f376ef7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/publish_lockfile.rs @@ -0,0 +1,591 @@ +//! Tests for including `Cargo.lock` when publishing/packaging. + +use std::fs::File; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{ + basic_manifest, cargo_process, git, paths, project, publish::validate_crate_contents, str, +}; + +fn pl_manifest(name: &str, version: &str, extra: &str) -> String { + format!( + r#" + [package] + name = "{}" + version = "{}" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + + {} + "#, + name, version, extra + ) +} + +#[cargo_test] +fn removed() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["publish-lockfile"] + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + publish-lockfile = true + license = "MIT" + description = "foo" + documentation = "foo" + homepage = "foo" + repository = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("package") + .masquerade_as_nightly_cargo(&["publish-lockfile"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the cargo feature `publish-lockfile` has been removed in the 1.37 release + + Remove the feature from Cargo.toml to remove this error. + See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#publish-lockfile for more information about using this feature. + +"#]]) + .run(); +} + +#[cargo_test] +fn package_lockfile() { + let p = project() + .file("Cargo.toml", &pl_manifest("foo", "0.0.1", "")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.root().join("target/package/foo-0.0.1.crate").is_file()); + p.cargo("package -l") + .with_stdout_data(str![[r#" +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("package") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.toml", "Cargo.toml.orig", "Cargo.lock", "src/main.rs"], + (), + ); +} + +#[cargo_test] +fn package_lockfile_git_repo() { + // Create a Git repository containing a minimal Rust project. + let g = git::repo(&paths::root().join("foo")) + .file("Cargo.toml", &pl_manifest("foo", "0.0.1", "")) + .file("src/main.rs", "fn main() {}") + .build(); + cargo_process("package -l") + .cwd(g.root()) + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + cargo_process("package -v") + .cwd(g.root()) + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] src/main.rs +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn lock_file_with_library() { + let p = project() + .file("Cargo.toml", &pl_manifest("foo", "0.0.1", "")) + .file("src/lib.rs", "") + .build(); + + p.cargo("package").run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + (), + ); +} + +#[cargo_test] +fn lock_file_and_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + .file("foo/Cargo.toml", &pl_manifest("foo", "0.0.1", "")) + .file("foo/src/main.rs", "fn main() {}") + .build(); + + p.cargo("package").cwd("foo").run(); + + let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/main.rs", "Cargo.lock"], + (), + ); +} + +#[cargo_test] +fn note_resolve_changes() { + // `multi` has multiple sources (path and registry). + Package::new("multi", "0.1.0").publish(); + // `updated` is always from registry, but should not change. + Package::new("updated", "1.0.0").publish(); + // `patched` is [patch]ed. + Package::new("patched", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + &pl_manifest( + "foo", + "0.0.1", + r#" + [dependencies] + multi = { path = "multi", version = "0.1" } + updated = "1.0" + patched = "1.0" + + [patch.crates-io] + patched = { path = "patched" } + "#, + ), + ) + .file("src/main.rs", "fn main() {}") + .file("multi/Cargo.toml", &basic_manifest("multi", "0.1.0")) + .file("multi/src/lib.rs", "") + .file("patched/Cargo.toml", &basic_manifest("patched", "1.0.0")) + .file("patched/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + // Make sure this does not change or warn. + Package::new("updated", "1.0.1").publish(); + + p.cargo("package --no-verify -v --allow-dirty") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[ARCHIVING] Cargo.lock +[UPDATING] `dummy-registry` index +[NOTE] package `multi v0.1.0` added to the packaged Cargo.lock file, was originally sourced from `[ROOT]/foo/multi` +[NOTE] package `patched v1.0.0` added to the packaged Cargo.lock file, was originally sourced from `[ROOT]/foo/patched` +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] src/main.rs +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] found (git) Cargo.toml ignored at `[..]/foo/Cargo.toml` in workdir `[..]` + +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn outdated_lock_version_change_does_not_warn() { + // If the version of the package being packaged changes, but Cargo.lock is + // not updated, don't bother warning about it. + let p = project() + .file("Cargo.toml", &pl_manifest("foo", "0.1.0", "")) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile").run(); + + p.change_file("Cargo.toml", &pl_manifest("foo", "0.2.0", "")); + + p.cargo("package --no-verify") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.2.0 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); +} + +#[cargo_test] +fn no_warn_workspace_extras() { + // Other entries in workspace lock file should be ignored. + Package::new("dep1", "1.0.0").publish(); + Package::new("dep2", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + &pl_manifest( + "a", + "0.1.0", + r#" + [dependencies] + dep1 = "1.0" + "#, + ), + ) + .file("a/src/main.rs", "fn main() {}") + .file( + "b/Cargo.toml", + &pl_manifest( + "b", + "0.1.0", + r#" + [dependencies] + dep2 = "1.0" + "#, + ), + ) + .file("b/src/main.rs", "fn main() {}") + .build(); + p.cargo("generate-lockfile").run(); + p.cargo("package --no-verify") + .cwd("a") + .with_stderr_data(str![[r#" +[PACKAGING] a v0.1.0 ([ROOT]/foo/a) +[UPDATING] `dummy-registry` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_package_with_yanked() { + Package::new("bar", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + &pl_manifest( + "foo", + "0.0.1", + r#" + [dependencies] + bar = "0.1" + "#, + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("generate-lockfile").run(); + Package::new("bar", "0.1.0").yanked(true).publish(); + // Make sure it sticks with the locked (yanked) version. + Package::new("bar", "0.1.1").publish(); + p.cargo("package --no-verify") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `dummy-registry` index +[WARNING] package `bar v0.1.0` in Cargo.lock is yanked in registry `crates-io`, consider updating to a version that is not yanked +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); +} + +#[cargo_test] +fn warn_install_with_yanked() { + Package::new("bar", "0.1.0").yanked(true).publish(); + Package::new("bar", "0.1.1").publish(); + Package::new("foo", "0.1.0") + .dep("bar", "0.1") + .file("src/main.rs", "fn main() {}") + .file( + "Cargo.lock", + r#" +[[package]] +name = "bar" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foo" +version = "0.1.0" +dependencies = [ + "bar 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + "#, + ) + .publish(); + + cargo_process("install --locked foo") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`) +[INSTALLING] foo v0.1.0 +[WARNING] package `bar v0.1.0` in Cargo.lock is yanked in registry `crates-io`, consider running without --locked +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[COMPILING] bar v0.1.0 +[COMPILING] foo v0.1.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.1.0` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); + + // Try again without --locked, make sure it uses 0.1.1 and does not warn. + cargo_process("install --force foo") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[INSTALLING] foo v0.1.0 +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.1 (registry `dummy-registry`) +[COMPILING] bar v0.1.1 +[COMPILING] foo v0.1.0 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[REPLACING] [ROOT]/home/.cargo/bin/foo[EXE] +[REPLACED] package `foo v0.1.0` with `foo v0.1.0` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn ignore_lockfile() { + // With an explicit `include` list, but Cargo.lock in .gitignore, don't + // complain about `Cargo.lock` being ignored. Note that it is still + // included in the packaged regardless. + let p = git::new("foo", |p| { + p.file( + "Cargo.toml", + &pl_manifest( + "foo", + "0.0.1", + r#" + include = [ + "src/main.rs" + ] + "#, + ), + ) + .file("src/main.rs", "fn main() {}") + .file(".gitignore", "Cargo.lock") + }); + p.cargo("package -l") + .with_stdout_data(str![[r#" +.cargo_vcs_info.json +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs + +"#]]) + .run(); + p.cargo("generate-lockfile").run(); + p.cargo("package -v") + .with_stderr_data(str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] src/main.rs +[PACKAGED] 5 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn ignore_lockfile_inner() { + // Ignore `Cargo.lock` if in .gitignore in a git subdirectory. + let p = git::new("foo", |p| { + p.no_manifest() + .file("bar/Cargo.toml", &pl_manifest("bar", "0.0.1", "")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/.gitignore", "Cargo.lock") + }); + p.cargo("generate-lockfile").cwd("bar").run(); + p.cargo("package -v --no-verify") + .cwd("bar") + .with_stderr_data(str![[r#" +[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar) +[ARCHIVING] .cargo_vcs_info.json +[ARCHIVING] .gitignore +[ARCHIVING] Cargo.lock +[ARCHIVING] Cargo.toml +[ARCHIVING] Cargo.toml.orig +[ARCHIVING] src/main.rs +[PACKAGED] 6 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) + +"#]]) + .run(); +} + +#[cargo_test] +fn use_workspace_root_lockfile() { + // Issue #11148 + // Workspace members should use `Cargo.lock` at workspace root + + Package::new("serde", "0.2.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies] + serde = "0.2" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "bar" + workspace = ".." + + [dependencies] + serde = "0.2" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + // Create `Cargo.lock` in the workspace root. + p.cargo("generate-lockfile").run(); + + // Now, add a newer version of `serde`. + Package::new("serde", "0.2.1").publish(); + + // Expect: package `bar` uses `serde v0.2.0` as required by workspace `Cargo.lock`. + p.cargo("package --workspace") + .with_stderr_data(str![[r#" +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] bar v0.0.1 ([ROOT]/foo/bar) +[UPDATING] `dummy-registry` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] bar v0.0.1 ([ROOT]/foo/bar) +[DOWNLOADING] crates ... +[DOWNLOADED] serde v0.2.0 (registry `dummy-registry`) +[COMPILING] serde v0.2.0 +[COMPILING] bar v0.0.1 ([ROOT]/foo/target/package/bar-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] serde v0.2.0 +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let package_path = p.root().join("target/package/foo-0.0.1.crate"); + assert!(package_path.is_file()); + let f = File::open(&package_path).unwrap(); + validate_crate_contents( + f, + "foo-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + (), + ); + + let package_path = p.root().join("target/package/bar-0.0.1.crate"); + assert!(package_path.is_file()); + let f = File::open(&package_path).unwrap(); + validate_crate_contents( + f, + "bar-0.0.1.crate", + &["Cargo.lock", "Cargo.toml", "Cargo.toml.orig", "src/main.rs"], + (), + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/read_manifest.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/read_manifest.rs new file mode 100644 index 000000000..3fbf6dfb3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/read_manifest.rs @@ -0,0 +1,236 @@ +//! Tests for the `cargo read-manifest` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_bin_manifest, main_file, project, str}; + +pub fn basic_bin_manifest_with_readme(name: &str, readme_filename: &str) -> String { + format!( + r#" + [package] + + name = "{}" + version = "0.5.0" + authors = ["wycats@example.com"] + readme = {} + + [[bin]] + + name = "{}" + "#, + name, readme_filename, name + ) +} + +#[cargo_test] +fn cargo_read_manifest_path_to_cargo_toml_relative() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest --manifest-path foo/Cargo.toml") + .cwd(p.root().parent().unwrap()) + .with_stdout_data( + str![[r#" +{ + "readme": null, + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_read_manifest_path_to_cargo_toml_absolute() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest --manifest-path") + .arg(p.root().join("Cargo.toml")) + .cwd(p.root().parent().unwrap()) + .with_stdout_data( + str![[r#" +{ + "readme": null, + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_read_manifest_path_to_cargo_toml_parent_relative() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest --manifest-path foo") + .cwd(p.root().parent().unwrap()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the manifest-path must be a path to a Cargo.toml file + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_read_manifest_path_to_cargo_toml_parent_absolute() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest --manifest-path") + .arg(p.root()) + .cwd(p.root().parent().unwrap()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the manifest-path must be a path to a Cargo.toml file + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_read_manifest_cwd() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest") + .with_stdout_data( + str![[r#" +{ + "readme": null, + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_read_manifest_with_specified_readme() { + let p = project() + .file( + "Cargo.toml", + &basic_bin_manifest_with_readme("foo", r#""SomeReadme.txt""#), + ) + .file("SomeReadme.txt", "Sample Project") + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest") + .with_stdout_data( + str![[r#" +{ + "readme": "SomeReadme.txt", + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} + +#[cargo_test] +fn cargo_read_manifest_default_readme() { + let assert_output = |readme, expected| { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file(readme, "Sample project") + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest").with_stdout_data(expected).run(); + }; + + assert_output( + "README.md", + str![[r#" +{ + "readme": "README.md", + "...": "{...}" +} +"#]] + .is_json(), + ); + + assert_output( + "README.txt", + str![[r#" +{ + "readme": "README.txt", + "...": "{...}" +} +"#]] + .is_json(), + ); + + assert_output( + "README", + str![[r#" +{ + "readme": "README", + "...": "{...}" +} +"#]] + .is_json(), + ); +} + +#[cargo_test] +fn cargo_read_manifest_suppress_default_readme() { + let p = project() + .file( + "Cargo.toml", + &basic_bin_manifest_with_readme("foo", "false"), + ) + .file("README.txt", "Sample project") + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest") + .with_stdout_data( + str![[r#" +{ + "readme": null, + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} + +// If a file named README.md exists, and `readme = true`, the value `README.md` should be defaulted in. +#[cargo_test] +fn cargo_read_manifest_defaults_readme_if_true() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest_with_readme("foo", "true")) + .file("README.md", "Sample project") + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("read-manifest") + .with_stdout_data( + str![[r#" +{ + "readme": "README.md", + "...": "{...}" +} +"#]] + .is_json(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry.rs new file mode 100644 index 000000000..e4c23f5c3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry.rs @@ -0,0 +1,4615 @@ +//! Tests for normal registry dependencies. + +use std::fmt::Write; +use std::fs::{self, File}; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use std::sync::Mutex; + +use cargo::core::SourceId; +use cargo_test_support::cargo_process; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{ + self, registry_path, Dependency, Package, RegistryBuilder, Response, TestRegistry, +}; +use cargo_test_support::{basic_manifest, project, str}; +use cargo_test_support::{git, t}; +use cargo_util::paths::remove_dir_all; + +fn setup_http() -> TestRegistry { + RegistryBuilder::new().http_index().build() +} + +#[cargo_test] +fn test_server_stops() { + let server = setup_http(); + server.join(); // ensure the server fully shuts down +} + +#[cargo_test] +fn simple_http() { + let _server = setup_http(); + simple( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn simple_git() { + simple( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn simple(pre_clean_expected: impl IntoData, post_clean_expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("check").with_stderr_data(pre_clean_expected).run(); + + p.cargo("clean").run(); + + assert!(paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file()); + + // Don't download a second time + p.cargo("check").with_stderr_data(post_clean_expected).run(); +} + +#[cargo_test] +fn deps_http() { + let _server = setup_http(); + deps(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn deps_git() { + deps(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn deps(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").publish(); + Package::new("bar", "0.0.1").dep("baz", "*").publish(); + + p.cargo("check").with_stderr_data(expected).run(); + + assert!(paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file()); +} + +#[cargo_test] +fn nonexistent_http() { + let _server = setup_http(); + nonexistent(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `nonexistent` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +#[cargo_test] +fn nonexistent_git() { + nonexistent(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `nonexistent` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +fn nonexistent(expected: impl IntoData) { + Package::new("init", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + nonexistent = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn wrong_case_http() { + let _server = setup_http(); + wrong_case(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package found +searched package name: `Init` +perhaps you meant: init +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +#[cargo_test] +fn wrong_case_git() { + wrong_case(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package found +searched package name: `Init` +perhaps you meant: init +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +fn wrong_case(expected: impl IntoData) { + Package::new("init", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + Init = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // #5678 to make this work + p.cargo("check") + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn mis_hyphenated_http() { + let _server = setup_http(); + mis_hyphenated(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package found +searched package name: `mis_hyphenated` +perhaps you meant: mis-hyphenated +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +#[cargo_test] +fn mis_hyphenated_git() { + mis_hyphenated(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package found +searched package name: `mis_hyphenated` +perhaps you meant: mis-hyphenated +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +fn mis_hyphenated(expected: impl IntoData) { + Package::new("mis-hyphenated", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + mis_hyphenated = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // #2775 to make this work + p.cargo("check") + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn wrong_version_http() { + let _server = setup_http(); + wrong_version( + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"` +candidate versions found which didn't match: 0.0.2, 0.0.1 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` +perhaps a crate was updated and forgotten to be re-vendored? + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"` +candidate versions found which didn't match: 0.0.4, 0.0.3, 0.0.2, ... +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` +perhaps a crate was updated and forgotten to be re-vendored? + +"#]], + ); +} + +#[cargo_test] +fn wrong_version_git() { + wrong_version( + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"` +candidate versions found which didn't match: 0.0.2, 0.0.1 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` +perhaps a crate was updated and forgotten to be re-vendored? + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `foo = ">=1.0.0"` +candidate versions found which didn't match: 0.0.4, 0.0.3, 0.0.2, ... +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` +perhaps a crate was updated and forgotten to be re-vendored? + +"#]], + ); +} + +fn wrong_version(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + foo = ">= 1.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("foo", "0.0.1").publish(); + Package::new("foo", "0.0.2").publish(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(pre_publish_expected) + .run(); + + Package::new("foo", "0.0.3").publish(); + Package::new("foo", "0.0.4").publish(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(post_publish_expected) + .run(); +} + +#[cargo_test] +fn bad_cksum_http() { + let _server = setup_http(); + bad_cksum(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bad-cksum v0.0.1 (registry `dummy-registry`) +[ERROR] failed to download replaced source registry `crates-io` + +Caused by: + failed to verify the checksum of `bad-cksum v0.0.1 (registry `dummy-registry`)` + +"#]]); +} + +#[cargo_test] +fn bad_cksum_git() { + bad_cksum(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bad-cksum v0.0.1 (registry `dummy-registry`) +[ERROR] failed to download replaced source registry `crates-io` + +Caused by: + failed to verify the checksum of `bad-cksum v0.0.1 (registry `dummy-registry`)` + +"#]]); +} + +fn bad_cksum(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bad-cksum = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + let pkg = Package::new("bad-cksum", "0.0.1"); + pkg.publish(); + t!(File::create(&pkg.archive_dst())); + + p.cargo("check -v") + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn update_registry_http() { + let _server = setup_http(); + update_registry( + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `notyet` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`) +[CHECKING] notyet v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn update_registry_git() { + update_registry( + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `notyet` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`) +[CHECKING] notyet v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn update_registry(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) { + Package::new("init", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + notyet = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(pre_publish_expected) + .run(); + + Package::new("notyet", "0.0.1").publish(); + + p.cargo("check") + .with_stderr_data(post_publish_expected) + .run(); +} + +#[cargo_test] +fn package_with_path_deps_http() { + let _server = setup_http(); + package_with_path_deps( + str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `dummy-registry` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `notyet` found + location searched: `dummy-registry` index (which is replacing registry `crates-io`) + required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `dummy-registry` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[DOWNLOADING] crates ... +[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`) +[COMPILING] notyet v0.0.1 +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn package_with_path_deps_git() { + package_with_path_deps( + str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `dummy-registry` index +[ERROR] failed to prepare local package for uploading + +Caused by: + no matching package named `notyet` found + location searched: `dummy-registry` index (which is replacing registry `crates-io`) + required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + str![[r#" +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `dummy-registry` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[DOWNLOADING] crates ... +[DOWNLOADED] notyet v0.0.1 (registry `dummy-registry`) +[COMPILING] notyet v0.0.1 +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn package_with_path_deps( + pre_publish_expected: impl IntoData, + post_publish_expected: impl IntoData, +) { + Package::new("init", "0.0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + repository = "bar" + + [dependencies.notyet] + version = "0.0.1" + path = "notyet" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("notyet/Cargo.toml", &basic_manifest("notyet", "0.0.1")) + .file("notyet/src/lib.rs", "") + .build(); + + p.cargo("package") + .with_status(101) + .with_stderr_data(pre_publish_expected) + .run(); + + Package::new("notyet", "0.0.1").publish(); + + p.cargo("package") + .with_stderr_data(post_publish_expected) + .run(); +} + +#[cargo_test] +fn lockfile_locks_http() { + let _server = setup_http(); + lockfile_locks( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn lockfile_locks_git() { + lockfile_locks( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn lockfile_locks(pre_publish_expected: impl IntoData, post_publish_expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("check") + .with_stderr_data(pre_publish_expected) + .run(); + + p.root().move_into_the_past(); + Package::new("bar", "0.0.2").publish(); + + p.cargo("check") + .with_stderr_data(post_publish_expected) + .run(); +} + +#[cargo_test] +fn lockfile_locks_transitively_http() { + let _server = setup_http(); + lockfile_locks_transitively( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn lockfile_locks_transitively_git() { + lockfile_locks_transitively( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn lockfile_locks_transitively( + pre_publish_expected: impl IntoData, + post_publish_expected: impl IntoData, +) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").publish(); + Package::new("bar", "0.0.1").dep("baz", "*").publish(); + + p.cargo("check") + .with_stderr_data(pre_publish_expected) + .run(); + + p.root().move_into_the_past(); + Package::new("baz", "0.0.2").publish(); + Package::new("bar", "0.0.2").dep("baz", "*").publish(); + + p.cargo("check") + .with_stderr_data(post_publish_expected) + .run(); +} + +#[cargo_test] +fn yanks_are_not_used_http() { + let _server = setup_http(); + yanks_are_not_used(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn yanks_are_not_used_git() { + yanks_are_not_used(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] ba[..] v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn yanks_are_not_used(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").publish(); + Package::new("baz", "0.0.2").yanked(true).publish(); + Package::new("bar", "0.0.1").dep("baz", "*").publish(); + Package::new("bar", "0.0.2") + .dep("baz", "*") + .yanked(true) + .publish(); + + p.cargo("check").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn relying_on_a_yank_is_bad_http() { + let _server = setup_http(); + relying_on_a_yank_is_bad(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `baz = "=0.0.2"` + version 0.0.2 is yanked +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `bar v0.0.1` + ... which satisfies dependency `bar = "*"` of package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +#[cargo_test] +fn relying_on_a_yank_is_bad_git() { + relying_on_a_yank_is_bad(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `baz = "=0.0.2"` + version 0.0.2 is yanked +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `bar v0.0.1` + ... which satisfies dependency `bar = "*"` of package `foo v0.0.1 ([ROOT]/foo)` + +"#]]); +} + +fn relying_on_a_yank_is_bad(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").publish(); + Package::new("baz", "0.0.2").yanked(true).publish(); + Package::new("bar", "0.0.1").dep("baz", "=0.0.2").publish(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn yanks_in_lockfiles_are_ok_http() { + let _server = setup_http(); + yanks_in_lockfiles_are_ok( + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "*"` + version 0.0.1 is yanked +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + ); +} + +#[cargo_test] +fn yanks_in_lockfiles_are_ok_git() { + yanks_in_lockfiles_are_ok( + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "*"` + version 0.0.1 is yanked +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + ); +} + +fn yanks_in_lockfiles_are_ok(expected_check: impl IntoData, expected_update: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("check").run(); + + registry_path().join("3").rm_rf(); + + Package::new("bar", "0.0.1").yanked(true).publish(); + + p.cargo("check").with_stderr_data(expected_check).run(); + + p.cargo("update") + .with_status(101) + .with_stderr_data(expected_update) + .run(); +} + +#[cargo_test] +fn yanks_in_lockfiles_are_ok_for_other_update_http() { + let _server = setup_http(); + yanks_in_lockfiles_are_ok_for_other_update( + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "*"` + version 0.0.1 is yanked +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] baz v0.0.1 -> v0.0.2 + +"#]], + ); +} + +#[cargo_test] +fn yanks_in_lockfiles_are_ok_for_other_update_git() { + yanks_in_lockfiles_are_ok_for_other_update( + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "*"` + version 0.0.1 is yanked +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] baz v0.0.1 -> v0.0.2 + +"#]], + ); +} + +fn yanks_in_lockfiles_are_ok_for_other_update( + expected_check: impl IntoData, + expected_update: impl IntoData, + expected_other_update: impl IntoData, +) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + baz = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + Package::new("baz", "0.0.1").publish(); + + p.cargo("check").run(); + + registry_path().join("3").rm_rf(); + + Package::new("bar", "0.0.1").yanked(true).publish(); + Package::new("baz", "0.0.1").publish(); + + p.cargo("check").with_stderr_data(expected_check).run(); + + Package::new("baz", "0.0.2").publish(); + + p.cargo("update") + .with_status(101) + .with_stderr_data(expected_update) + .run(); + + p.cargo("update baz") + .with_stderr_data(expected_other_update) + .run(); +} + +#[cargo_test] +fn yanks_in_lockfiles_are_ok_with_new_dep_http() { + let _server = setup_http(); + yanks_in_lockfiles_are_ok_with_new_dep(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ADDING] baz v0.0.1 +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn yanks_in_lockfiles_are_ok_with_new_dep_git() { + yanks_in_lockfiles_are_ok_with_new_dep(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ADDING] baz v0.0.1 +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`) +[CHECKING] baz v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn yanks_in_lockfiles_are_ok_with_new_dep(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("check").run(); + + registry_path().join("3").rm_rf(); + + Package::new("bar", "0.0.1").yanked(true).publish(); + Package::new("baz", "0.0.1").publish(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + baz = "*" + "#, + ); + + p.cargo("check").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn update_with_lockfile_if_packages_missing_http() { + let _server = setup_http(); + update_with_lockfile_if_packages_missing(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn update_with_lockfile_if_packages_missing_git() { + update_with_lockfile_if_packages_missing(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn update_with_lockfile_if_packages_missing(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + p.cargo("check").run(); + p.root().move_into_the_past(); + + paths::home().join(".cargo/registry").rm_rf(); + p.cargo("check").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn update_lockfile_http() { + let _server = setup_http(); + update_lockfile( + str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] bar v0.0.1 -> v0.0.2 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`) +[CHECKING] bar v0.0.2 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.0.2 -> v0.0.3 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.3 (registry `dummy-registry`) +[CHECKING] bar v0.0.3 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[UPDATING] bar v0.0.3 -> v0.0.4 +[ADDING] spam v0.2.5 + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.0.4 -> v0.0.5 +[REMOVING] spam v0.2.5 + +"#]], + ); +} + +#[cargo_test] +fn update_lockfile_git() { + update_lockfile( + str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] bar v0.0.1 -> v0.0.2 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.2 (registry `dummy-registry`) +[CHECKING] bar v0.0.2 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.0.2 -> v0.0.3 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.3 (registry `dummy-registry`) +[CHECKING] bar v0.0.3 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[UPDATING] bar v0.0.3 -> v0.0.4 +[ADDING] spam v0.2.5 + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.0.4 -> v0.0.5 +[REMOVING] spam v0.2.5 + +"#]], + ); +} + +fn update_lockfile( + expected_update: impl IntoData, + expected_check: impl IntoData, + expected_other_update: impl IntoData, + expected_other_check: impl IntoData, + expected_new_update: impl IntoData, + expected_new_check: impl IntoData, +) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + println!("0.0.1"); + Package::new("bar", "0.0.1").publish(); + p.cargo("check").run(); + + Package::new("bar", "0.0.2").publish(); + Package::new("bar", "0.0.3").publish(); + paths::home().join(".cargo/registry").rm_rf(); + println!("0.0.2 update"); + p.cargo("update bar --precise 0.0.2") + .with_stderr_data(expected_update) + .run(); + + println!("0.0.2 build"); + p.cargo("check").with_stderr_data(expected_check).run(); + + println!("0.0.3 update"); + p.cargo("update bar") + .with_stderr_data(expected_other_update) + .run(); + + println!("0.0.3 build"); + p.cargo("check") + .with_stderr_data(expected_other_check) + .run(); + + 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 bar") + .with_stderr_data(expected_new_update) + .run(); + + println!("new dependencies update"); + Package::new("bar", "0.0.5").publish(); + p.cargo("update bar") + .with_stderr_data(expected_new_check) + .run(); +} + +#[cargo_test] +fn dev_dependency_not_used_http() { + let _server = setup_http(); + dev_dependency_not_used(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn dev_dependency_not_used_git() { + dev_dependency_not_used(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn dev_dependency_not_used(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").publish(); + Package::new("bar", "0.0.1").dev_dep("baz", "*").publish(); + + p.cargo("check").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn bad_license_file_http() { + let registry = setup_http(); + bad_license_file( + ®istry, + str![[r#" +... +[ERROR] license-file `foo` does not appear to exist (relative to `[ROOT]/foo`). +... +"#]], + ); +} + +#[cargo_test] +fn bad_license_file_git() { + let registry = registry::init(); + bad_license_file( + ®istry, + str![[r#" +... +[ERROR] license-file `foo` does not appear to exist (relative to `[ROOT]/foo`). +... +"#]], + ); +} + +fn bad_license_file(registry: &TestRegistry, expected: impl IntoData) { + Package::new("foo", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license-file = "foo" + description = "bar" + repository = "baz" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p.cargo("publish -v") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn updating_a_dep_http() { + let _server = setup_http(); + updating_a_dep( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.0.1 -> v0.1.0 +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn updating_a_dep_git() { + updating_a_dep( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.0.1 -> v0.1.0 +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 +[CHECKING] a v0.0.1 ([ROOT]/foo/a) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn updating_a_dep(pre_update_expected: impl IntoData, post_update_expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.a] + path = "a" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("check").with_stderr_data(pre_update_expected).run(); + assert!(paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file()); + + // Now delete the CACHEDIR.TAG file: this is the situation we'll be in after + // upgrading from a version of Cargo that doesn't mark this directory, to one that + // does. It should be recreated. + fs::remove_file(paths::home().join(".cargo/registry/CACHEDIR.TAG")) + .expect("remove CACHEDIR.TAG"); + + p.change_file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + "#, + ); + Package::new("bar", "0.1.0").publish(); + + println!("second"); + p.cargo("check") + .with_stderr_data(post_update_expected) + .run(); + + assert!( + paths::home().join(".cargo/registry/CACHEDIR.TAG").is_file(), + "CACHEDIR.TAG recreated in existing registry" + ); +} + +#[cargo_test] +fn git_and_registry_dep_http() { + let _server = setup_http(); + git_and_registry_dep( + str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/b` +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.0.1 (registry `dummy-registry`) +[CHECKING] a v0.0.1 +[CHECKING] b v0.0.1 ([ROOTURL]/b#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn git_and_registry_dep_git() { + git_and_registry_dep( + str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/b` +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.0.1 (registry `dummy-registry`) +[CHECKING] a v0.0.1 +[CHECKING] b v0.0.1 ([ROOTURL]/b#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn git_and_registry_dep(pre_move_expected: impl IntoData, post_move_expected: impl IntoData) { + let b = git::repo(&paths::root().join("b")) + .file( + "Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = "0.0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = "0.0.1" + + [dependencies.b] + git = '{}' + "#, + b.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("a", "0.0.1").publish(); + + p.root().move_into_the_past(); + p.cargo("check").with_stderr_data(pre_move_expected).run(); + p.root().move_into_the_past(); + + println!("second"); + p.cargo("check").with_stderr_data(post_move_expected).run(); +} + +#[cargo_test] +fn update_publish_then_update_http() { + let _server = setup_http(); + update_publish_then_update(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.1.1 (registry `dummy-registry`) +[COMPILING] a v0.1.1 +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn update_publish_then_update_git() { + update_publish_then_update(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.1.1 (registry `dummy-registry`) +[COMPILING] a v0.1.1 +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn update_publish_then_update(expected: impl IntoData) { + // First generate a Cargo.lock and a clone of the registry index at the + // "head" of the current registry. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + Package::new("a", "0.1.0").publish(); + p.cargo("build").run(); + + // Next, publish a new package and back up the copy of the registry we just + // created. + Package::new("a", "0.1.1").publish(); + let registry = paths::home().join(".cargo/registry"); + let backup = paths::root().join("registry-backup"); + t!(fs::rename(®istry, &backup)); + + // Generate a Cargo.lock with the newer version, and then move the old copy + // of the registry back into place. + let p2 = project() + .at("foo2") + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = "0.1.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + p2.cargo("build").run(); + registry.rm_rf(); + t!(fs::rename(&backup, ®istry)); + t!(fs::rename( + p2.root().join("Cargo.lock"), + p.root().join("Cargo.lock") + )); + + // Finally, build the first project again (with our newer Cargo.lock) which + // should force an update of the old registry, download the new crate, and + // then build everything again. + p.cargo("build").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn fetch_downloads_http() { + let _server = setup_http(); + fetch_downloads(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.1.0 (registry `dummy-registry`) + +"#]]); +} + +#[cargo_test] +fn fetch_downloads_git() { + fetch_downloads(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.1.0 (registry `dummy-registry`) + +"#]]); +} + +fn fetch_downloads(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("a", "0.1.0").publish(); + + p.cargo("fetch").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn update_transitive_dependency_http() { + let _server = setup_http(); + update_transitive_dependency( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] b v0.1.0 -> v0.1.1 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] b v0.1.1 (registry `dummy-registry`) +[CHECKING] b v0.1.1 +[CHECKING] a v0.1.0 +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn update_transitive_dependency_git() { + update_transitive_dependency( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] b v0.1.0 -> v0.1.1 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] b v0.1.1 (registry `dummy-registry`) +[CHECKING] b v0.1.1 +[CHECKING] a v0.1.0 +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn update_transitive_dependency(expected_update: impl IntoData, expected_check: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("a", "0.1.0").dep("b", "*").publish(); + Package::new("b", "0.1.0").publish(); + + p.cargo("fetch").run(); + + Package::new("b", "0.1.1").publish(); + + p.cargo("update b").with_stderr_data(expected_update).run(); + + p.cargo("check").with_stderr_data(expected_check).run(); +} + +#[cargo_test] +fn update_backtracking_ok_http() { + let _server = setup_http(); + update_backtracking_ok(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[UPDATING] hyper v0.6.5 -> v0.6.6 +[UPDATING] openssl v0.1.0 -> v0.1.1 + +"#]]); +} + +#[cargo_test] +fn update_backtracking_ok_git() { + update_backtracking_ok(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[UPDATING] hyper v0.6.5 -> v0.6.6 +[UPDATING] openssl v0.1.0 -> v0.1.1 + +"#]]); +} + +fn update_backtracking_ok(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + webdriver = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("webdriver", "0.1.0") + .dep("hyper", "0.6") + .publish(); + Package::new("hyper", "0.6.5") + .dep("openssl", "0.1") + .dep("cookie", "0.1") + .publish(); + Package::new("cookie", "0.1.0") + .dep("openssl", "0.1") + .publish(); + Package::new("openssl", "0.1.0").publish(); + + p.cargo("generate-lockfile").run(); + + Package::new("openssl", "0.1.1").publish(); + Package::new("hyper", "0.6.6") + .dep("openssl", "0.1.1") + .dep("cookie", "0.1.0") + .publish(); + + p.cargo("update hyper").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn update_multiple_packages_http() { + let _server = setup_http(); + update_multiple_packages( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[UPDATING] a v0.1.0 -> v0.1.1 +[UPDATING] b v0.1.0 -> v0.1.1 +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] c v0.1.0 -> v0.1.1 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] a v0.1.1 (registry `dummy-registry`) +[DOWNLOADED] b v0.1.1 (registry `dummy-registry`) +[DOWNLOADED] c v0.1.1 (registry `dummy-registry`) +[CHECKING] a v0.1.1 +[CHECKING] c v0.1.1 +[CHECKING] b v0.1.1 +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +#[cargo_test] +fn update_multiple_packages_git() { + update_multiple_packages( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[UPDATING] a v0.1.0 -> v0.1.1 +[UPDATING] b v0.1.0 -> v0.1.1 +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]], + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] c v0.1.0 -> v0.1.1 + +"#]], + str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] c v0.1.1 (registry `dummy-registry`) +[DOWNLOADED] b v0.1.1 (registry `dummy-registry`) +[DOWNLOADED] a v0.1.1 (registry `dummy-registry`) +[CHECKING] b v0.1.1 +[CHECKING] a v0.1.1 +[CHECKING] c v0.1.1 +[CHECKING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]], + ); +} + +fn update_multiple_packages( + expected_update: impl IntoData, + expected_other_update: impl IntoData, + expected_check: impl IntoData, +) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + a = "*" + b = "*" + c = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("a", "0.1.0").publish(); + Package::new("b", "0.1.0").publish(); + Package::new("c", "0.1.0").publish(); + + p.cargo("fetch").run(); + + Package::new("a", "0.1.1").publish(); + Package::new("b", "0.1.1").publish(); + Package::new("c", "0.1.1").publish(); + + p.cargo("update a b") + .with_stderr_data(expected_update) + .run(); + + p.cargo("update b c") + .with_stderr_data(expected_other_update) + .run(); + + p.cargo("check") + .with_stderr_data(IntoData::unordered(expected_check)) + .run(); +} + +#[cargo_test] +fn bundled_crate_in_registry_http() { + let _server = setup_http(); + bundled_crate_in_registry(); +} + +#[cargo_test] +fn bundled_crate_in_registry_git() { + bundled_crate_in_registry(); +} + +fn bundled_crate_in_registry() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + baz = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.1.0").publish(); + Package::new("baz", "0.1.0") + .dep("bar", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar", version = "0.1.0" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "") + .publish(); + + p.cargo("run").run(); +} + +#[cargo_test] +fn update_same_prefix_oh_my_how_was_this_a_bug_http() { + let _server = setup_http(); + update_same_prefix_oh_my_how_was_this_a_bug(); +} + +#[cargo_test] +fn update_same_prefix_oh_my_how_was_this_a_bug_git() { + update_same_prefix_oh_my_how_was_this_a_bug(); +} + +fn update_same_prefix_oh_my_how_was_this_a_bug() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "ugh" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("foobar", "0.2.0").publish(); + Package::new("foo", "0.1.0") + .dep("foobar", "0.2.0") + .publish(); + + p.cargo("generate-lockfile").run(); + p.cargo("update foobar --precise=0.2.0").run(); +} + +#[cargo_test] +fn use_semver_http() { + let _server = setup_http(); + use_semver(); +} + +#[cargo_test] +fn use_semver_git() { + use_semver(); +} + +fn use_semver() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "1.2.3-alpha.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("foo", "1.2.3-alpha.0").publish(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn use_semver_package_incorrectly_http() { + let _server = setup_http(); + use_semver_package_incorrectly(str![[r#" +[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: [ROOT]/foo/a +required by package `b v0.1.0 ([ROOT]/foo/b)` +if you are looking for the prerelease package it needs to be specified explicitly + a = { version = "0.1.1-alpha.0" } + +"#]]); +} + +#[cargo_test] +fn use_semver_package_incorrectly_git() { + use_semver_package_incorrectly(str![[r#" +[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: [ROOT]/foo/a +required by package `b v0.1.0 ([ROOT]/foo/b)` +if you are looking for the prerelease package it needs to be specified explicitly + a = { version = "0.1.1-alpha.0" } + +"#]]); +} + +fn use_semver_package_incorrectly(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.1-alpha.0" + edition = "2015" + authors = [] + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { version = "^0.1", path = "../a" } + "#, + ) + .file("a/src/main.rs", "fn main() {}") + .file("b/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn only_download_relevant_http() { + let _server = setup_http(); + only_download_relevant(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`) +[CHECKING] baz v0.1.0 +[CHECKING] bar v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn only_download_relevant_git() { + only_download_relevant(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.0 (registry `dummy-registry`) +[CHECKING] baz v0.1.0 +[CHECKING] bar v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn only_download_relevant(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [target.foo.dependencies] + foo = "*" + [dev-dependencies] + bar = "*" + [dependencies] + baz = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("foo", "0.1.0").publish(); + Package::new("bar", "0.1.0").publish(); + Package::new("baz", "0.1.0").publish(); + + p.cargo("check").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn resolve_and_backtracking_http() { + let _server = setup_http(); + resolve_and_backtracking(); +} + +#[cargo_test] +fn resolve_and_backtracking_git() { + resolve_and_backtracking(); +} + +fn resolve_and_backtracking() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("foo", "0.1.1") + .feature_dep("bar", "0.1", &["a", "b"]) + .publish(); + Package::new("foo", "0.1.0").publish(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn upstream_warnings_on_extra_verbose_http() { + let _server = setup_http(); + upstream_warnings_on_extra_verbose(str![[r#" +... +[WARNING] function `unused` is never used +... +"#]]); +} + +#[cargo_test] +fn upstream_warnings_on_extra_verbose_git() { + upstream_warnings_on_extra_verbose(str![[r#" +... +[WARNING] function `unused` is never used +... +"#]]); +} + +fn upstream_warnings_on_extra_verbose(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("foo", "0.1.0") + .file("src/lib.rs", "fn unused() {}") + .publish(); + + p.cargo("check -vv").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn disallow_network_http() { + let _server = setup_http(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check --frozen") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to get `foo` as a dependency of package `bar v0.5.0 ([ROOT]/foo)` + +Caused by: + failed to query replaced source registry `crates-io` + +Caused by: + attempting to make an HTTP request, but --frozen was specified + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_network_git() { + let _server = RegistryBuilder::new().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "*" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check --frozen") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `foo` as a dependency of package `bar v0.5.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `foo` + +Caused by: + Unable to update registry `crates-io` + +Caused by: + failed to update replaced source registry `crates-io` + +Caused by: + attempting to make an HTTP request, but --frozen was specified + +"#]]) + .run(); +} + +#[cargo_test] +fn add_dep_dont_update_registry_http() { + let _server = setup_http(); + add_dep_dont_update_registry(str![[r#" +[CHECKING] bar v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn add_dep_dont_update_registry_git() { + add_dep_dont_update_registry(str![[r#" +[CHECKING] bar v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn add_dep_dont_update_registry(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "baz" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + remote = "0.3" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + Package::new("remote", "0.3.4").publish(); + + p.cargo("check").run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "baz" } + remote = "0.3" + "#, + ); + + p.cargo("check").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn bump_version_dont_update_registry_http() { + let _server = setup_http(); + bump_version_dont_update_registry(str![[r#" +[CHECKING] bar v0.6.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +#[cargo_test] +fn bump_version_dont_update_registry_git() { + bump_version_dont_update_registry(str![[r#" +[CHECKING] bar v0.6.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]); +} + +fn bump_version_dont_update_registry(expected: impl IntoData) { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "baz" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + remote = "0.3" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + Package::new("remote", "0.3.4").publish(); + + p.cargo("check").run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.6.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "baz" } + "#, + ); + + p.cargo("check").with_stderr_data(expected).run(); +} + +#[cargo_test] +fn toml_lies_but_index_is_truth_http() { + let _server = setup_http(); + toml_lies_but_index_is_truth(); +} + +#[cargo_test] +fn toml_lies_but_index_is_truth_git() { + toml_lies_but_index_is_truth(); +} + +fn toml_lies_but_index_is_truth() { + Package::new("foo", "0.2.0").publish(); + Package::new("bar", "0.3.0") + .dep("foo", "0.2.0") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.3.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.1.0" + "#, + ) + .file("src/lib.rs", "extern crate foo;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.3" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -v").run(); +} + +#[cargo_test] +fn vv_prints_warnings_http() { + let _server = setup_http(); + vv_prints_warnings(); +} + +#[cargo_test] +fn vv_prints_warnings_git() { + vv_prints_warnings(); +} + +fn vv_prints_warnings() { + Package::new("foo", "0.2.0") + .file( + "src/lib.rs", + "#![deny(warnings)] fn foo() {} // unused function", + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "fo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -vv").run(); +} + +#[cargo_test] +fn bad_and_or_malicious_packages_rejected_http() { + let _server = setup_http(); + bad_and_or_malicious_packages_rejected(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.2.0 (registry `dummy-registry`) +[ERROR] failed to download replaced source registry `crates-io` + +Caused by: + failed to unpack package `foo v0.2.0 (registry `dummy-registry`)` + +Caused by: + invalid tarball downloaded, contains a file at "foo-0.1.0/src/lib.rs" which isn't under "foo-0.2.0" + +"#]]); +} + +#[cargo_test] +fn bad_and_or_malicious_packages_rejected_git() { + bad_and_or_malicious_packages_rejected(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.2.0 (registry `dummy-registry`) +[ERROR] failed to download replaced source registry `crates-io` + +Caused by: + failed to unpack package `foo v0.2.0 (registry `dummy-registry`)` + +Caused by: + invalid tarball downloaded, contains a file at "foo-0.1.0/src/lib.rs" which isn't under "foo-0.2.0" + +"#]]); +} + +fn bad_and_or_malicious_packages_rejected(expected: impl IntoData) { + Package::new("foo", "0.2.0") + .extra_file("foo-0.1.0/src/lib.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "fo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -vv") + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn git_init_templatedir_missing_http() { + let _server = setup_http(); + git_init_templatedir_missing(); +} + +#[cargo_test] +fn git_init_templatedir_missing_git() { + git_init_templatedir_missing(); +} + +fn git_init_templatedir_missing() { + Package::new("foo", "0.2.0").dep("bar", "*").publish(); + Package::new("bar", "0.2.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "fo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.2" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); + + remove_dir_all(paths::home().join(".cargo/registry")).unwrap(); + fs::write( + paths::home().join(".gitconfig"), + r#" + [init] + templatedir = nowhere + "#, + ) + .unwrap(); + + p.cargo("check").run(); + p.cargo("check").run(); +} + +#[cargo_test] +fn rename_deps_and_features_http() { + let _server = setup_http(); + rename_deps_and_features(); +} + +#[cargo_test] +fn rename_deps_and_features_git() { + rename_deps_and_features(); +} + +fn rename_deps_and_features() { + Package::new("foo", "0.1.0") + .file("src/lib.rs", "pub fn f1() {}") + .publish(); + Package::new("foo", "0.2.0") + .file("src/lib.rs", "pub fn f2() {}") + .publish(); + Package::new("bar", "0.2.0") + .add_dep( + Dependency::new("foo01", "0.1.0") + .package("foo") + .optional(true), + ) + .add_dep(Dependency::new("foo02", "0.2.0").package("foo")) + .feature("another", &["foo01"]) + .file( + "src/lib.rs", + r#" + extern crate foo02; + #[cfg(feature = "foo01")] + extern crate foo01; + + pub fn foo() { + foo02::f2(); + #[cfg(feature = "foo01")] + foo01::f1(); + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.2" + "#, + ) + .file( + "src/main.rs", + " + extern crate bar; + fn main() { bar::foo(); } + ", + ) + .build(); + + p.cargo("check").run(); + p.cargo("check --features bar/foo01").run(); + p.cargo("check --features bar/another").run(); +} + +#[cargo_test] +fn ignore_invalid_json_lines_http() { + let _server = setup_http(); + ignore_invalid_json_lines(); +} + +#[cargo_test] +fn ignore_invalid_json_lines_git() { + ignore_invalid_json_lines(); +} + +fn ignore_invalid_json_lines() { + Package::new("foo", "0.1.0").publish(); + Package::new("foo", "0.1.1") + .invalid_index_line(true) + .publish(); + Package::new("foo", "0.2.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = '0.1.0' + foo02 = { version = '0.2.0', package = 'foo' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn invalid_json_lines_error() { + Package::new("foo", "0.1.0") + .rust_version("1.0") + .schema_version(2) + .publish(); + Package::new("foo", "0.1.1") + // Bad name field, too corrupt to use + .invalid_index_line(true) + .publish(); + Package::new("foo", "0.1.2") + // Bad version field, too corrupt to use + .index_line( + r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":{},"links":null,"name":"foo","vers":"bad","yanked":false,"rust_version":"1.2345","v":1000000000}"#, + ) + .publish(); + Package::new("foo", "0.1.3") + // Bad field, report rust version + .index_line( + r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.3","yanked":false,"rust_version":"1.2345","v":1000000000}"#, + ) + .publish(); + Package::new("foo", "0.1.4") + // Bad field, report schema + .index_line( + r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.4","yanked":false,"v":1000000000}"#, + ) + .publish(); + Package::new("foo", "0.1.5") + // Bad field, report error + .index_line( + r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.5","yanked":false}"#, + ) + .publish(); + Package::new("foo", "0.1.6") + // Bad field with bad rust version, report schema + .index_line( + r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.6","yanked":false,"rust_version":"bad","v":1000000000}"#, + ) + .publish(); + Package::new("foo", "0.1.7") + // Bad field with bad rust version and schema, report error + .index_line( + r#"{"cksum":"7ca5fc2301ad96ade45356faf53225aea36437d99930bbfa951155c01faecf79","deps":[],"features":"bad","links":null,"name":"foo","vers":"0.1.7","yanked":false,"rust_version":"bad","v":"bad"}"#, + ) + .publish(); + Package::new("foo", "0.2.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.1.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `foo = "^0.1.1"` + version 0.1.3 requires cargo 1.2345 + version 0.1.4 requires a Cargo version that supports index version 1000000000 + version 0.1.5's index entry is invalid + version 0.1.6 requires a Cargo version that supports index version 1000000000 + version 0.1.7's index entry is invalid +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `a v0.5.0 ([ROOT]/foo)` + +"#]]) + .run(); + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `foo = "^0.1.1"` + version 0.1.3 requires cargo 1.2345 + version 0.1.4 requires a Cargo version that supports index version 1000000000 + version 0.1.5's index entry is invalid + version 0.1.6 requires a Cargo version that supports index version 1000000000 + version 0.1.7's index entry is invalid +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `a v0.5.0 ([ROOT]/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +fn readonly_registry_still_works_http() { + let _server = setup_http(); + readonly_registry_still_works(); +} + +#[cargo_test] +fn readonly_registry_still_works_git() { + readonly_registry_still_works(); +} + +fn readonly_registry_still_works() { + Package::new("foo", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = '0.1.0' + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + p.cargo("fetch --locked").run(); + chmod_readonly(&paths::home(), true); + p.cargo("check").run(); + // make sure we un-readonly the files afterwards so "cargo clean" can remove them (#6934) + chmod_readonly(&paths::home(), false); + + fn chmod_readonly(path: &Path, readonly: bool) { + for entry in t!(path.read_dir()) { + let entry = t!(entry); + let path = entry.path(); + if t!(entry.file_type()).is_dir() { + chmod_readonly(&path, readonly); + } else { + set_readonly(&path, readonly); + } + } + set_readonly(path, readonly); + } + + fn set_readonly(path: &Path, readonly: bool) { + let mut perms = t!(path.metadata()).permissions(); + perms.set_readonly(readonly); + t!(fs::set_permissions(path, perms)); + } +} + +#[cargo_test(ignore_windows = "On Windows setting file attributes is a bit complicated")] +fn unaccessible_registry_cache_still_works() { + Package::new("foo", "0.1.0").publish(); + Package::new("fo2", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = '0.1.0' + fo2 = '0.1.0' + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + p.cargo("fetch --locked").run(); + + let cache_path = inner_dir(&paths::cargo_home().join("registry/index")).join(".cache"); + let f_cache_path = cache_path.join("3/f"); + + // Remove the permissions from the cache path that contains the "foo" crate + set_permissions(&f_cache_path, 0o000); + + // Now run a build and make sure we properly build and warn the user + p.cargo("build") + .with_stderr_data(str![[r#" +[WARNING] failed to write cache, path: [ROOT]/home/.cargo/registry/index/-[HASH]/.cache/3/f/fo[..], [ERROR] Permission denied (os error 13) +[COMPILING] fo[..] v0.1.0 +[COMPILING] fo[..] v0.1.0 +[COMPILING] a v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + // make sure we add the permissions to the files afterwards so "cargo clean" can remove them (#6934) + set_permissions(&f_cache_path, 0o777); + + #[cfg_attr(windows, allow(unused_variables))] + fn set_permissions(path: &Path, permissions: u32) { + #[cfg(not(windows))] + { + use std::os::unix::fs::PermissionsExt; + let mut perms = t!(path.metadata()).permissions(); + perms.set_mode(permissions); + t!(fs::set_permissions(path, perms)); + } + + #[cfg(windows)] + panic!("This test is not supported on windows. See the reason in the #[cargo_test] macro"); + } + + fn inner_dir(path: &Path) -> PathBuf { + for entry in t!(path.read_dir()) { + let path = t!(entry).path(); + + if path.is_dir() { + return path; + } + } + + panic!("could not find inner directory of {path:?}"); + } +} + +#[cargo_test] +fn registry_index_rejected_http() { + let _server = setup_http(); + registry_index_rejected( + str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the `registry.index` config value is no longer supported + Use `[source]` replacement to alter the default index for crates.io. + +"#]], + str![[r#" +[ERROR] the `registry.index` config value is no longer supported +Use `[source]` replacement to alter the default index for crates.io. + +"#]], + ); +} + +#[cargo_test] +fn registry_index_rejected_git() { + registry_index_rejected( + str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + the `registry.index` config value is no longer supported + Use `[source]` replacement to alter the default index for crates.io. + +"#]], + str![[r#" +[ERROR] the `registry.index` config value is no longer supported +Use `[source]` replacement to alter the default index for crates.io. + +"#]], + ); +} + +fn registry_index_rejected(expected_check: impl IntoData, expected_login: impl IntoData) { + Package::new("dep", "0.1.0").publish(); + + let p = project() + .file( + ".cargo/config.toml", + r#" + [registry] + index = "https://example.com/" + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(expected_check) + .run(); + + p.cargo("login") + .with_status(101) + .with_stderr_data(expected_login) + .run(); +} + +#[cargo_test] +fn package_lock_inside_package_is_overwritten() { + let registry = registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1") + .file("src/lib.rs", "") + .file(".cargo-ok", "") + .publish(); + + p.cargo("check").run(); + + let id = SourceId::for_registry(registry.index_url()).unwrap(); + let hash = cargo::util::hex::short_hash(&id); + let ok = paths::cargo_home() + .join("registry") + .join("src") + .join(format!("-{}", hash)) + .join("bar-0.0.1") + .join(".cargo-ok"); + + assert_eq!(ok.metadata().unwrap().len(), 7); +} + +#[cargo_test] +fn package_lock_as_a_symlink_inside_package_is_overwritten() { + let registry = registry::init(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1") + .file("src/lib.rs", "pub fn f() {}") + .symlink(".cargo-ok", "src/lib.rs") + .publish(); + + p.cargo("check").run(); + + let id = SourceId::for_registry(registry.index_url()).unwrap(); + let hash = cargo::util::hex::short_hash(&id); + let pkg_root = paths::cargo_home() + .join("registry") + .join("src") + .join(format!("-{}", hash)) + .join("bar-0.0.1"); + let ok = pkg_root.join(".cargo-ok"); + let librs = pkg_root.join("src/lib.rs"); + + // Is correctly overwritten and doesn't affect the file linked to + assert_eq!(ok.metadata().unwrap().len(), 7); + assert_eq!(fs::read_to_string(librs).unwrap(), "pub fn f() {}"); +} + +#[cargo_test] +fn ignores_unknown_index_version_http() { + let _server = setup_http(); + ignores_unknown_index_version(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + +"#]]); +} + +#[cargo_test] +fn ignores_unknown_index_version_git() { + ignores_unknown_index_version(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + +"#]]); +} + +fn ignores_unknown_index_version(expected: impl IntoData) { + // 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(u32::MAX) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree").with_stdout_data(expected).run(); +} + +#[cargo_test] +fn unknown_index_version_error() { + Package::new("bar", "0.0.1").publish(); + // 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" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "^1.0"` + version 1.0.1 requires a Cargo version that supports index version 4294967295 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "^1.0"` + version 1.0.1 requires a Cargo version that supports index version 4294967295 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +fn unknown_index_version_with_msrv_error() { + Package::new("bar", "0.0.1").publish(); + // If the version field is not understood, it is ignored. + Package::new("bar", "1.0.1") + .schema_version(u32::MAX) + .rust_version("1.2345") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `bar = "^1.0"` + version 1.0.1 requires cargo 1.2345 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); +} + +#[cargo_test] +fn protocol() { + cargo_process("install bar") + .with_status(101) + .env("CARGO_REGISTRIES_CRATES_IO_PROTOCOL", "invalid") + .with_stderr_data(str![[r#" +[ERROR] unsupported registry protocol `invalid` (defined in environment variable `CARGO_REGISTRIES_CRATES_IO_PROTOCOL`) + +"#]]) + .run(); +} + +#[cargo_test] +fn http_requires_trailing_slash() { + cargo_process("install bar --index sparse+https://invalid.crates.io/test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] sparse registry url must end in a slash `/`: sparse+https://invalid.crates.io/test + +"#]]) + .run(); +} + +// Limit the test to debug builds so that `__CARGO_TEST_MAX_UNPACK_SIZE` will take affect. +#[cfg(debug_assertions)] +#[cargo_test] +fn reach_max_unpack_size() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // Size of bar.crate is around 180 bytes. + Package::new("bar", "0.0.1").publish(); + + p.cargo("check") + .env("__CARGO_TEST_MAX_UNPACK_SIZE", "8") // hit 8 bytes limit and boom! + .env("__CARGO_TEST_MAX_UNPACK_RATIO", "0") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[ERROR] failed to download replaced source registry `crates-io` + +Caused by: + failed to unpack package `bar v0.0.1 (registry `dummy-registry`)` + +Caused by: + failed to iterate over archive + +Caused by: + maximum limit reached when reading + +"#]]) + .run(); + + // Restore to the default ratio and it should compile. + p.cargo("check") + .env("__CARGO_TEST_MAX_UNPACK_SIZE", "8") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn sparse_blocking_count() { + let fail_count = Mutex::new(0); + let _registry = RegistryBuilder::new() + .http_index() + .add_responder("/index/3/b/bar", move |req, server| { + let mut fail_count = fail_count.lock().unwrap(); + if *fail_count < 1 { + *fail_count += 1; + server.internal_server_error(req) + } else { + server.index(req) + } + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + // Ensure we have the expected number of `block_until_ready` calls. + // The 1st (0 transfers pending), is the deliberate extra call in `ensure_loaded` for a source. + // The 2nd (1 transfers pending), is the registry `config.json`. + // the 3rd (1 transfers pending), is the package metadata for `bar`. + + p.cargo("check") + .env("CARGO_LOG", "network::HttpRegistry::block_until_ready=trace") + .with_stderr_data(str![[r#" + [..] TRACE network::HttpRegistry::block_until_ready: 0 transfers pending +[UPDATING] `dummy-registry` index + [..] TRACE network::HttpRegistry::block_until_ready: 1 transfers pending + [..] TRACE network::HttpRegistry::block_until_ready: 1 transfers pending +[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `[..]/index/3/b/bar` ([..]), got 500 +body: +internal server error +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn sparse_retry_single() { + let fail_count = Mutex::new(0); + let _registry = RegistryBuilder::new() + .http_index() + .add_responder("/index/3/b/bar", move |req, server| { + let mut fail_count = fail_count.lock().unwrap(); + if *fail_count < 2 { + *fail_count += 1; + server.internal_server_error(req) + } else { + server.index(req) + } + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("bar", "0.0.1").publish(); + + p.cargo("check").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 500 +body: +internal server error +[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 500 +body: +internal server error +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn sparse_retry_multiple() { + // Tests retry behavior of downloading lots of packages with various + // failure rates accessing the sparse index. + + // The index is the number of retries, the value is the number of packages + // that retry that number of times. Thus 50 packages succeed on first try, + // 25 on second, etc. + const RETRIES: &[u32] = &[50, 25, 12, 6]; + + let pkgs: Vec<_> = RETRIES + .iter() + .enumerate() + .flat_map(|(retries, num)| { + (0..*num) + .into_iter() + .map(move |n| (retries as u32, format!("{}-{n}-{retries}", rand_prefix()))) + }) + .collect(); + + let mut builder = RegistryBuilder::new().http_index(); + let fail_counts: Arc>> = Arc::new(Mutex::new(vec![0; pkgs.len()])); + let mut cargo_toml = r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + "# + .to_string(); + // The expected stderr output. + let mut expected = "\ +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +" + .to_string(); + for (n, (retries, name)) in pkgs.iter().enumerate() { + let count_clone = fail_counts.clone(); + let retries = *retries; + let ab = &name[..2]; + let cd = &name[2..4]; + builder = builder.add_responder(format!("/index/{ab}/{cd}/{name}"), move |req, server| { + let mut fail_counts = count_clone.lock().unwrap(); + if fail_counts[n] < retries { + fail_counts[n] += 1; + server.internal_server_error(req) + } else { + server.index(req) + } + }); + write!(&mut cargo_toml, "{name} = \"1.0.0\"\n").unwrap(); + for retry in 0..retries { + let remain = 3 - retry; + write!( + &mut expected, + "[WARNING] spurious network error ({remain} tries remaining): \ + failed to get successful HTTP response from \ + `http://127.0.0.1:[..]/{ab}/{cd}/{name}` (127.0.0.1), got 500\n\ + body:\n\ + internal server error\n" + ) + .unwrap(); + } + write!( + &mut expected, + "\ +[DOWNLOADED] {name} v1.0.0 (registry `dummy-registry`) +" + ) + .unwrap(); + } + write!( + &mut expected, + "\ +[LOCKING] 93 packages to latest compatible versions +" + ) + .unwrap(); + let _server = builder.build(); + for (_, name) in &pkgs { + Package::new(name, "1.0.0").publish(); + } + let p = project() + .file("Cargo.toml", &cargo_toml) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_stderr_data(IntoData::unordered(expected)) + .run(); +} + +#[cargo_test] +fn dl_retry_single() { + // Tests retry behavior of downloading a package. + // This tests a single package which exercises the code path that causes + // it to block. + let fail_count = Mutex::new(0); + let _server = RegistryBuilder::new() + .http_index() + .add_responder("/dl/bar/1.0.0/download", move |req, server| { + let mut fail_count = fail_count.lock().unwrap(); + if *fail_count < 2 { + *fail_count += 1; + server.internal_server_error(req) + } else { + server.dl(req) + } + }) + .build(); + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 500 +body: +internal server error +[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 500 +body: +internal server error +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) + +"#]]).run(); +} + +/// Creates a random prefix to randomly spread out the package names +/// to somewhat evenly distribute the different failures at different +/// points. +fn rand_prefix() -> String { + use rand::Rng; + const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyz"; + let mut rng = rand::rng(); + (0..5) + .map(|_| CHARS[rng.random_range(0..CHARS.len())] as char) + .collect() +} + +#[cargo_test] +fn dl_retry_multiple() { + // Tests retry behavior of downloading lots of packages with various + // failure rates. + + // The index is the number of retries, the value is the number of packages + // that retry that number of times. Thus 50 packages succeed on first try, + // 25 on second, etc. + const RETRIES: &[u32] = &[50, 25, 12, 6]; + + let pkgs: Vec<_> = RETRIES + .iter() + .enumerate() + .flat_map(|(retries, num)| { + (0..*num) + .into_iter() + .map(move |n| (retries as u32, format!("{}-{n}-{retries}", rand_prefix()))) + }) + .collect(); + + let mut builder = RegistryBuilder::new().http_index(); + let fail_counts: Arc>> = Arc::new(Mutex::new(vec![0; pkgs.len()])); + let mut cargo_toml = r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + "# + .to_string(); + // The expected stderr output. + let mut expected = "\ +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +" + .to_string(); + for (n, (retries, name)) in pkgs.iter().enumerate() { + let count_clone = fail_counts.clone(); + let retries = *retries; + builder = + builder.add_responder(format!("/dl/{name}/1.0.0/download"), move |req, server| { + let mut fail_counts = count_clone.lock().unwrap(); + if fail_counts[n] < retries { + fail_counts[n] += 1; + server.internal_server_error(req) + } else { + server.dl(req) + } + }); + write!(&mut cargo_toml, "{name} = \"1.0.0\"\n").unwrap(); + for retry in 0..retries { + let remain = 3 - retry; + write!( + &mut expected, + "[WARNING] spurious network error ({remain} tries remaining): \ + failed to get successful HTTP response from \ + `http://127.0.0.1:[..]/dl/{name}/1.0.0/download` (127.0.0.1), got 500\n\ + body:\n\ + internal server error\n" + ) + .unwrap(); + } + write!( + &mut expected, + "[DOWNLOADED] {name} v1.0.0 (registry `dummy-registry`)\n" + ) + .unwrap(); + } + write!( + &mut expected, + "[LOCKING] 93 packages to latest compatible versions\n" + ) + .unwrap(); + let _server = builder.build(); + for (_, name) in &pkgs { + Package::new(name, "1.0.0").publish(); + } + let p = project() + .file("Cargo.toml", &cargo_toml) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_stderr_data(IntoData::unordered(expected)) + .run(); +} + +#[cargo_test] +fn deleted_entry() { + // Checks the behavior when a package is removed from the index. + // This is done occasionally on crates.io to handle things like + // copyright takedowns. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // First, test removing a single version, but leaving an older version. + Package::new("bar", "0.1.0").publish(); + let bar_path = Path::new("3/b/bar"); + let bar_reg_path = registry_path().join(&bar_path); + let old_index = fs::read_to_string(&bar_reg_path).unwrap(); + Package::new("bar", "0.1.1").publish(); + p.cargo("tree") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.1 (registry `dummy-registry`) + +"#]]) + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v0.1.1 + +"#]]) + .run(); + + // Remove 0.1.1 + fs::remove_file(paths::root().join("dl/bar/0.1.1/download")).unwrap(); + let repo = git2::Repository::open(registry_path()).unwrap(); + let mut index = repo.index().unwrap(); + fs::write(&bar_reg_path, &old_index).unwrap(); + index.add_path(&bar_path).unwrap(); + index.write().unwrap(); + git::commit(&repo); + + // With `Cargo.lock` unchanged, it shouldn't have an impact. + p.cargo("tree") + .with_stderr_data("") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v0.1.1 + +"#]]) + .run(); + + // Regenerating Cargo.lock should switch to old version. + fs::remove_file(p.root().join("Cargo.lock")).unwrap(); + p.cargo("tree") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.1.0 (registry `dummy-registry`) + +"#]]) + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v0.1.0 + +"#]]) + .run(); + + // Remove the package entirely. + fs::remove_file(paths::root().join("dl/bar/0.1.0/download")).unwrap(); + let mut index = repo.index().unwrap(); + index.remove(&bar_path, 0).unwrap(); + index.write().unwrap(); + git::commit(&repo); + fs::remove_file(&bar_reg_path).unwrap(); + + // With `Cargo.lock` unchanged, it shouldn't have an impact. + p.cargo("tree") + .with_stderr_data("") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v0.1.0 + +"#]]) + .run(); + + // Regenerating Cargo.lock should fail. + fs::remove_file(p.root().join("Cargo.lock")).unwrap(); + p.cargo("tree") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `bar` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn corrupted_ok_overwritten() { + // Checks what happens if .cargo-ok gets truncated, such as if the file is + // created, but the flush/close is interrupted. + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) + +"#]]) + .run(); + let ok = glob::glob( + paths::home() + .join(".cargo/registry/src/*/bar-1.0.0/.cargo-ok") + .to_str() + .unwrap(), + ) + .unwrap() + .next() + .unwrap() + .unwrap(); + // Simulate cargo being interrupted, or filesystem corruption. + fs::write(&ok, "").unwrap(); + assert_eq!(fs::read_to_string(&ok).unwrap(), ""); + p.cargo("fetch").with_stderr_data("").run(); + assert_eq!(fs::read_to_string(&ok).unwrap(), r#"{"v":1}"#); +} + +#[cargo_test] +fn not_found_permutations() { + // Test for querying permutations for a missing dependency. + let misses = Arc::new(Mutex::new(Vec::new())); + let misses2 = misses.clone(); + let _registry = RegistryBuilder::new() + .http_index() + .not_found_handler(move |req, _server| { + let mut misses = misses2.lock().unwrap(); + misses.push(req.url.path().to_string()); + Response { + code: 404, + headers: vec![], + body: b"not found".to_vec(), + } + }) + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a-b_c = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `a-b_c` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]) + .run(); + let mut misses = misses.lock().unwrap(); + misses.sort(); + assert_eq!( + &*misses, + &[ + "/index/a-/b-/a-b-c", + "/index/a-/b_/a-b_c", + "/index/a_/b_/a_b_c" + ] + ); +} + +#[cargo_test] +fn default_auth_error() { + // Check for the error message for an authentication error when default is set. + let crates_io = RegistryBuilder::new().http_api().build(); + let _alternative = RegistryBuilder::new().http_api().alternative().build(); + + paths::home().join(".cargo/credentials.toml").rm_rf(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Test output before setting the default. + p.cargo("publish --no-verify") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] no token found, please run `cargo login` +or use environment variable CARGO_REGISTRY_TOKEN + +"#]]) + .with_status(101) + .run(); + + p.cargo("publish --no-verify --registry alternative") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] no token found for `alternative`, please run `cargo login --registry alternative` +or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +"#]]) + .with_status(101) + .run(); + + // Test the output with the default. + cargo_util::paths::append( + &paths::cargo_home().join("config.toml"), + br#" + [registry] + default = "alternative" + "#, + ) + .unwrap(); + + p.cargo("publish --no-verify") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] no token found for `alternative`, please run `cargo login --registry alternative` +or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +"#]]) + .with_status(101) + .run(); + + p.cargo("publish --no-verify --registry crates-io") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] no token found, please run `cargo login --registry crates-io` +or use environment variable CARGO_REGISTRY_TOKEN + +"#]]) + .with_status(101) + .run(); +} + +const SAMPLE_HEADERS: &[&str] = &[ + "x-amz-cf-pop: SFO53-P2", + "x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA==", + "x-cache: Hit from cloudfront", + "server: AmazonS3", + "x-amz-version-id: pvsJYY_JGsWiSETZvLJKb7DeEW5wWq1W", + "x-amz-server-side-encryption: AES256", + "content-type: text/plain", + "via: 1.1 bcbc5b46216015493e082cfbcf77ef10.cloudfront.net (CloudFront)", +]; + +#[cargo_test] +fn debug_header_message_index() { + // The error message should include some headers for debugging purposes. + let _server = RegistryBuilder::new() + .http_index() + .add_responder("/index/3/b/bar", |_, _| Response { + code: 503, + headers: SAMPLE_HEADERS.iter().map(|s| s.to_string()).collect(), + body: b"Please slow down".to_vec(), + }) + .build(); + Package::new("bar", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503 +body: +Please slow down +[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503 +body: +Please slow down +[WARNING] spurious network error (1 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503 +body: +Please slow down +[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to query replaced source registry `crates-io` + +Caused by: + download of 3/b/bar failed + +Caused by: + failed to get successful HTTP response from `http://127.0.0.1:[..]/index/3/b/bar` (127.0.0.1), got 503 + debug headers: + x-amz-cf-pop: SFO53-P2 + x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA== + x-cache: Hit from cloudfront + body: + Please slow down + +"#]]) + .run(); +} + +#[cargo_test] +fn debug_header_message_dl() { + // Same as debug_header_message_index, but for the dl endpoint which goes + // through a completely different code path. + let _server = RegistryBuilder::new() + .http_index() + .add_responder("/dl/bar/1.0.0/download", |_, _| Response { + code: 503, + headers: SAMPLE_HEADERS.iter().map(|s| s.to_string()).collect(), + body: b"Please slow down".to_vec(), + }) + .build(); + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[WARNING] spurious network error (3 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503 +body: +Please slow down +[WARNING] spurious network error (2 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503 +body: +Please slow down +[WARNING] spurious network error (1 tries remaining): failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503 +body: +Please slow down +[ERROR] failed to download from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` + +Caused by: + failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/1.0.0/download` (127.0.0.1), got 503 + debug headers: + x-amz-cf-pop: SFO53-P2 + x-amz-cf-id: vEc3osJrCAXVaciNnF4Vev-hZFgnYwmNZtxMKRJ5bF6h9FTOtbTMnA== + x-cache: Hit from cloudfront + body: + Please slow down + +"#]]) + .run(); +} + +#[cfg(unix)] +#[cargo_test] +fn set_mask_during_unpacking() { + use std::os::unix::fs::MetadataExt; + + Package::new("bar", "1.0.0") + .file_with_mode("example.sh", 0o777, "#!/bin/sh") + .file_with_mode("src/lib.rs", 0o666, "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) + +"#]]) + .run(); + let src_file_path = |path: &str| { + glob::glob( + paths::home() + .join(".cargo/registry/src/*/bar-1.0.0/") + .join(path) + .to_str() + .unwrap(), + ) + .unwrap() + .next() + .unwrap() + .unwrap() + }; + + let umask = cargo::util::get_umask(); + let metadata = fs::metadata(src_file_path("src/lib.rs")).unwrap(); + assert_eq!(metadata.mode() & 0o777, 0o666 & !umask); + let metadata = fs::metadata(src_file_path("example.sh")).unwrap(); + assert_eq!(metadata.mode() & 0o777, 0o777 & !umask); +} + +#[cargo_test] +fn unpack_again_when_cargo_ok_is_unrecognized() { + Package::new("bar", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) + +"#]]) + .run(); + + let src_file_path = |path: &str| { + glob::glob( + paths::home() + .join(".cargo/registry/src/*/bar-1.0.0/") + .join(path) + .to_str() + .unwrap(), + ) + .unwrap() + .next() + .unwrap() + .unwrap() + }; + + // Change permissions to simulate the old behavior not respecting umask. + let lib_rs = src_file_path("src/lib.rs"); + let cargo_ok = src_file_path(".cargo-ok"); + let mut perms = fs::metadata(&lib_rs).unwrap().permissions(); + assert!(!perms.readonly()); + perms.set_readonly(true); + fs::set_permissions(&lib_rs, perms).unwrap(); + let ok = fs::read_to_string(&cargo_ok).unwrap(); + assert_eq!(&ok, r#"{"v":1}"#); + + p.cargo("fetch").with_stderr_data("").run(); + + // Without changing `.cargo-ok`, a unpack won't be triggered. + let perms = fs::metadata(&lib_rs).unwrap().permissions(); + assert!(perms.readonly()); + + // Write "ok" to simulate the old behavior and trigger the unpack again. + fs::write(&cargo_ok, "ok").unwrap(); + + p.cargo("fetch").with_stderr_data("").run(); + + // Permission has been restored and `.cargo-ok` is in the new format. + let perms = fs::metadata(lib_rs).unwrap().permissions(); + assert!(!perms.readonly()); + let ok = fs::read_to_string(&cargo_ok).unwrap(); + assert_eq!(&ok, r#"{"v":1}"#); +} + +#[cargo_test] +fn differ_only_by_metadata() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "=0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1+b").publish(); + Package::new("baz", "0.0.1+c").yanked(true).publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.0.1+b (registry `dummy-registry`) +[CHECKING] baz v0.0.1+b +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + Package::new("baz", "0.0.1+d").publish(); + + p.cargo("clean").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] baz v0.0.1+b +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn differ_only_by_metadata_with_lockfile() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "=0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1+a").publish(); + Package::new("baz", "0.0.1+b").publish(); + Package::new("baz", "0.0.1+c").publish(); + + p.cargo("update --package baz --precise 0.0.1+b") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] baz v0.0.1+c -> v0.0.1+b + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.0.1+b (registry `dummy-registry`) +[CHECKING] baz v0.0.1+b +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn builtin_source_replacement() { + // errors for builtin source replacement of crates.io + // should not include mention of source replacement in the error message. + let server = RegistryBuilder::new().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bad-cksum = ">= 0.0.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + let pkg = Package::new("bad-cksum", "0.0.1"); + pkg.publish(); + t!(File::create(&pkg.archive_dst())); + + p.cargo("check -v") + .replace_crates_io(&server.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bad-cksum v0.0.1 +[ERROR] failed to verify the checksum of `bad-cksum v0.0.1` + +"#]]) + .run(); +} + +#[cargo_test] +fn builtin_source_replacement_no_vendor_error() { + // errors for builtin source replacement of crates.io + // should not mention outdated vendor dependencies + let server = RegistryBuilder::new().build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + + [dependencies] + dep = "0.2.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + let pkg = Package::new("dep", "0.1.0"); + pkg.publish(); + + p.cargo("check -v") + .replace_crates_io(&server.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] failed to select a version for the requirement `dep = "^0.2.0"` +candidate versions found which didn't match: 0.1.0 +location searched: crates.io index +required by package `foo v0.0.1 ([ROOT]/foo)` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_auth.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_auth.rs new file mode 100644 index 000000000..360402965 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_auth.rs @@ -0,0 +1,575 @@ +//! Tests for registry authentication. + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Package, RegistryBuilder, Token}; +use cargo_test_support::str; +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(&["asymmetric-token"]) + .arg("-Zasymmetric-token"); + e.env( + "CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS", + "cargo:paseto cargo:token", + ); + e +} + +fn make_project() -> Project { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + version = "0.0.1" + registry = "alternative" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + Package::new("bar", "0.0.1").alternative(true).publish(); + p +} + +#[cargo_test] +fn requires_credential_provider() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .http_api() + .build(); + + let p = make_project(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[ERROR] failed to download `bar v0.0.1 (registry `alternative`)` + +Caused by: + 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(); +} + +#[cargo_test] +fn simple() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .http_index() + .build(); + + let p = make_project(); + cargo(&p, "build") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[COMPILING] bar v0.0.1 (registry `alternative`) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_with_asymmetric() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .http_index() + .token(cargo_test_support::registry::Token::rfc_key()) + .build(); + + let p = make_project(); + cargo(&p, "build") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[COMPILING] bar v0.0.1 (registry `alternative`) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn environment_config() { + let registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_registry() + .no_configure_token() + .http_index() + .build(); + let p = make_project(); + cargo(&p, "build") + .env( + "CARGO_REGISTRIES_ALTERNATIVE_INDEX", + registry.index_url().as_str(), + ) + .env("CARGO_REGISTRIES_ALTERNATIVE_TOKEN", registry.token()) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[COMPILING] bar v0.0.1 (registry `alternative`) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn environment_token() { + let registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_index() + .build(); + + let p = make_project(); + cargo(&p, "build") + .env("CARGO_REGISTRIES_ALTERNATIVE_TOKEN", registry.token()) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[COMPILING] bar v0.0.1 (registry `alternative`) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn environment_token_with_asymmetric() { + let registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_index() + .token(cargo_test_support::registry::Token::Keys( + "k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36" + .to_string(), + None, + )) + .build(); + + let p = make_project(); + cargo(&p, "build") + .env("CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY", registry.key()) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `alternative`) +[COMPILING] bar v0.0.1 (registry `alternative`) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn bad_environment_token_with_asymmetric_subject() { + let registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_index() + .token(cargo_test_support::registry::Token::Keys( + "k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36" + .to_string(), + None, + )) + .build(); + + let p = make_project(); + cargo(&p, "build") + .env("CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY", registry.key()) + .env( + "CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY_SUBJECT", + "incorrect", + ) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + token rejected for `alternative`, please run `cargo login --registry alternative` + or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +Caused by: + failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401 + body: + Unauthorized message from server. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn bad_environment_token_with_asymmetric_incorrect_subject() { + let registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_index() + .token(cargo_test_support::registry::Token::rfc_key()) + .build(); + + let p = make_project(); + cargo(&p, "build") + .env("CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY", registry.key()) + .env( + "CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY_SUBJECT", + "incorrect", + ) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + token rejected for `alternative`, please run `cargo login --registry alternative` + or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +Caused by: + failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401 + body: + Unauthorized message from server. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn bad_environment_token_with_incorrect_asymmetric() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_index() + .token(cargo_test_support::registry::Token::Keys( + "k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36" + .to_string(), + None, + )) + .build(); + + let p = make_project(); + cargo(&p, "build") + .env( + "CARGO_REGISTRIES_ALTERNATIVE_SECRET_KEY", + "k3.secret.9Vxr5hVlI_g_orBZN54vPz20bmB4O76wB_MVqUSuJJJqHFLwP8kdn_RY5g6J6pQG", + ) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + token rejected for `alternative`, please run `cargo login --registry alternative` + or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +Caused by: + failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401 + body: + Unauthorized message from server. + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn missing_token() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_index() + .build(); + + let p = make_project(); + cargo(&p, "build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + no token found for `alternative`, please run `cargo login --registry alternative` + or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +"#]]) + .run(); +} + +#[cargo_test] +fn missing_token_git() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .build(); + + let p = make_project(); + cargo(&p, "build") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[ERROR] failed to download `bar v0.0.1 (registry `alternative`)` + +Caused by: + unable to get packages from source + +Caused by: + no token found for `alternative`, please run `cargo login --registry alternative` + or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +"#]]) + .run(); +} + +#[cargo_test] +fn incorrect_token() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_index() + .build(); + + let p = make_project(); + cargo(&p, "build") + .env("CARGO_REGISTRIES_ALTERNATIVE_TOKEN", "incorrect") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + token rejected for `alternative`, please run `cargo login --registry alternative` + or use environment variable CARGO_REGISTRIES_ALTERNATIVE_TOKEN + +Caused by: + failed to get successful HTTP response from `http://127.0.0.1:[..]/index/config.json`, got 401 + body: + Unauthorized message from server. + +"#]]) + .run(); +} + +#[cargo_test] +fn incorrect_token_git() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .http_api() + .build(); + + let p = make_project(); + cargo(&p, "build") + .env("CARGO_REGISTRIES_ALTERNATIVE_TOKEN", "incorrect") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[ERROR] failed to download from `http://127.0.0.1:[..]/dl/bar/0.0.1/download` + +Caused by: + failed to get successful HTTP response from `http://127.0.0.1:[..]/dl/bar/0.0.1/download` (127.0.0.1), got 401 + body: + Unauthorized message from server. + +"#]]) + .run(); +} + +#[cargo_test] +fn anonymous_alt_registry() { + // An alternative registry that requires auth, but is not in the config. + let registry = RegistryBuilder::new() + .alternative() + .auth_required() + .no_configure_token() + .no_configure_registry() + .http_index() + .build(); + + let p = make_project(); + cargo(&p, &format!("install --index {} bar", registry.index_url())) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index +[ERROR] no token found for `sparse+http://127.0.0.1:[..]/index/` +consider setting up an alternate registry in Cargo's configuration +as described by https://doc.rust-lang.org/cargo/reference/registries.html + +[registries] +my-registry = { index = "sparse+http://127.0.0.1:[..]/index/" } + + +"#]]) + .run(); +} + +#[cargo_test] +fn login() { + let _registry = RegistryBuilder::new() + .alternative() + .no_configure_token() + .auth_required() + .http_index() + .build(); + + let p = make_project(); + cargo(&p, "login --registry alternative") + .with_stdin("sekrit") + .run(); +} + +#[cargo_test] +fn login_existing_token() { + let _registry = RegistryBuilder::new() + .alternative() + .auth_required() + .http_index() + .build(); + + let p = make_project(); + cargo(&p, "login --registry alternative") + .with_stdin("sekrit") + .run(); +} + +#[cargo_test] +fn duplicate_index() { + let server = RegistryBuilder::new() + .alternative() + .no_configure_token() + .auth_required() + .build(); + let p = make_project(); + + // Two alternative registries with the same index. + cargo(&p, "build") + .env( + "CARGO_REGISTRIES_ALTERNATIVE1_INDEX", + server.index_url().as_str(), + ) + .env( + "CARGO_REGISTRIES_ALTERNATIVE2_INDEX", + server.index_url().as_str(), + ) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[LOCKING] 1 package to latest compatible version +[ERROR] failed to download `bar v0.0.1 (registry `alternative`)` + +Caused by: + unable to get packages from source + +Caused by: + multiple registries are configured with the same index url 'registry+[ROOTURL]/alternative-registry': alternative1, alternative2 + +"#]]) + .run(); +} + +#[cargo_test] +fn token_not_logged() { + // Checks that the token isn't displayed in debug output (for both HTTP + // index and registry API). Note that this doesn't fully verify the + // correct behavior since we don't have an HTTP2 server, and curl behaves + // significantly differently when using HTTP2. + let crates_io = RegistryBuilder::new() + .http_api() + .http_index() + .auth_required() + .token(Token::Plaintext("a-unique_token".to_string())) + .build(); + Package::new("bar", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + let output = cargo(&p, "publish") + .replace_crates_io(crates_io.index_url()) + .env("CARGO_HTTP_DEBUG", "true") + .env("CARGO_LOG", "trace") + .run(); + let log = String::from_utf8(output.stderr).unwrap(); + assert_e2e().eq( + &log, + str![[r#" +... +[PUBLISHED] foo v0.1.0 at registry `crates-io` + +"#]], + ); + let authorizations: Vec<_> = log + .lines() + .filter(|line| { + line.contains("http-debug:") && line.to_lowercase().contains("authorization") + }) + .collect(); + assert!(authorizations.iter().all(|line| line.contains("REDACTED"))); + // Total authorizations: + // 1. Initial config.json + // 2. /index/3/f/foo + // 3. config.json again for verification + // 4. /index/3/b/bar + // 5. config.json again for verification + // 6. /index/3/b/bar + // 7. /dl/bar/1.0.0/download + // 8. /api/v1/crates/new + // 9. config.json again for verification + // 10. /index/3/f/foo for the "wait for publish" + assert_eq!(authorizations.len(), 10); + assert!(!log.contains("a-unique_token")); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_overlay.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_overlay.rs new file mode 100644 index 000000000..3733fb826 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/registry_overlay.rs @@ -0,0 +1,306 @@ +//! Tests for local-registry sources. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::{Package, RegistryBuilder, TestRegistry}; +use cargo_test_support::str; + +fn setup() -> (TestRegistry, String) { + let alt = RegistryBuilder::new().alternative().build(); + ( + RegistryBuilder::new().http_index().build(), + alt.index_url() + .to_file_path() + .unwrap() + .into_os_string() + .into_string() + .unwrap(), + ) +} + +#[cargo_test] +fn overlay_hit() { + let (reg, alt_path) = setup(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // baz is only in the local registry, but it gets found + Package::new("baz", "0.1.1") + .alternative(true) + .local(true) + .publish(); + + p.cargo("check") + .overlay_registry(®.index_url(), &alt_path) + .run(); +} + +#[cargo_test] +fn registry_version_wins() { + let (reg, alt_path) = setup(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // The latest one is in the main registry, so it will get chosen. + Package::new("baz", "0.1.1").publish(); + Package::new("baz", "0.1.0") + .alternative(true) + .local(true) + .publish(); + + p.cargo("check") + .overlay_registry(®.index_url(), &alt_path) + .with_stderr_data(str![[r#" +[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.1 (registry `sparse+http://127.0.0.1:[..]/index/`) +[CHECKING] baz v0.1.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn overlay_version_wins() { + let (reg, alt_path) = setup(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // The latest one is in the overlay registry, so it will get chosen. + Package::new("baz", "0.1.0").publish(); + Package::new("baz", "0.1.1") + .alternative(true) + .local(true) + .publish(); + + p.cargo("check") + .overlay_registry(®.index_url(), &alt_path) + .with_stderr_data(str![[r#" +[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index +[LOCKING] 1 package to latest compatible version +[UNPACKING] baz v0.1.1 (registry `[ROOT]/alternative-registry`) +[CHECKING] baz v0.1.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn version_precedence() { + let (reg, alt_path) = setup(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // The one we want is in the main registry. + Package::new("baz", "0.1.1").publish(); + Package::new("baz", "0.1.1") + .alternative(true) + .local(true) + .publish(); + + p.cargo("check") + .overlay_registry(®.index_url(), &alt_path) + .with_stderr_data(str![[r#" +[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index +[LOCKING] 1 package to latest compatible version +[UNPACKING] baz v0.1.1 (registry `[ROOT]/alternative-registry`) +[CHECKING] baz v0.1.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn local_depends_on_old_registry_package() { + let (reg, alt_path) = setup(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.1.0" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("baz", "0.0.1").publish(); + // A new local package can depend on an older version in the registry. + Package::new("baz", "0.1.1") + .dep("baz", "=0.0.1") + .alternative(true) + .local(true) + .publish(); + + p.cargo("check") + .overlay_registry(®.index_url(), &alt_path) + .run(); +} + +#[cargo_test] +fn registry_dep_depends_on_new_local_package() { + let (reg, alt_path) = setup(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + registry-package = "0.1.0" + workspace-package = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + Package::new("registry-package", "0.1.0") + .dep("workspace-package", "0.1.0") + .publish(); + // The local overlay contains an updated version of workspace-package + Package::new("workspace-package", "0.1.1") + .alternative(true) + .local(true) + .publish(); + + // The registry contains older versions of workspace-package (one of which + // we depend on directly). + Package::new("workspace-package", "0.1.0").publish(); + Package::new("workspace-package", "0.0.1").publish(); + + p.cargo("check") + .overlay_registry(®.index_url(), &alt_path) + .with_stderr_data( + str![[r#" +[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index +[LOCKING] 3 packages to latest compatible versions +[ADDING] workspace-package v0.0.1 (available: v0.1.1) +[DOWNLOADING] crates ... +[UNPACKING] workspace-package v0.1.1 (registry `[ROOT]/alternative-registry`) +[DOWNLOADED] registry-package v0.1.0 (registry `sparse+http://127.0.0.1:[..]/index/`) +[DOWNLOADED] workspace-package v0.0.1 (registry `sparse+http://127.0.0.1:[..]/index/`) +[CHECKING] workspace-package v0.1.1 +[CHECKING] workspace-package v0.0.1 +[CHECKING] registry-package v0.1.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +// Test that we can overlay on top of alternate registries, not just crates-io. +// Since the test framework only supports a single alternate registry, we repurpose +// the dummy crates-io as the registry to overlay on top. +#[cargo_test] +fn alt_registry() { + let alt = RegistryBuilder::new().http_index().alternative().build(); + let crates_io = RegistryBuilder::new().build(); + let crates_io_path = crates_io + .index_url() + .to_file_path() + .unwrap() + .into_os_string() + .into_string() + .unwrap(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = { version = "0.1.0", registry = "alternative" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // This package isn't used, but publishing it forces the creation of the registry index. + Package::new("bar", "0.0.1").local(true).publish(); + Package::new("baz", "0.1.1").alternative(true).publish(); + + p.cargo("check") + .overlay_registry(&alt.index_url(), &crates_io_path) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rename_deps.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rename_deps.rs new file mode 100644 index 000000000..a31641f94 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rename_deps.rs @@ -0,0 +1,406 @@ +//! Tests for renaming dependencies. + +use cargo_test_support::git; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package}; +use cargo_test_support::{basic_manifest, project, str}; + +#[cargo_test] +fn rename_dependency() { + 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.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { version = "0.1.0" } + baz = { version = "0.2.0", package = "bar" } + "#, + ) + .file("src/lib.rs", "extern crate bar; extern crate baz;") + .build(); + + p.cargo("build").run(); +} + +#[cargo_test] +fn rename_with_different_names() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "bar", package = "bar" } + "#, + ) + .file("src/lib.rs", "extern crate baz;") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "random_name" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build").run(); +} + +#[cargo_test] +fn lots_of_names() { + registry::alt_init(); + Package::new("foo", "0.1.0") + .file("src/lib.rs", "pub fn foo1() {}") + .publish(); + Package::new("foo", "0.2.0") + .file("src/lib.rs", "pub fn foo() {}") + .publish(); + Package::new("foo", "0.1.0") + .file("src/lib.rs", "pub fn foo2() {}") + .alternative(true) + .publish(); + + let g = git::repo(&paths::root().join("another")) + .file("Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("src/lib.rs", "pub fn foo3() {}") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.2" + foo1 = {{ version = "0.1", package = "foo" }} + foo2 = {{ version = "0.1", registry = "alternative", package = "foo" }} + foo3 = {{ git = '{}', package = "foo" }} + foo4 = {{ path = "foo", package = "foo" }} + "#, + g.url() + ), + ) + .file( + "src/lib.rs", + " + extern crate foo; + extern crate foo1; + extern crate foo2; + extern crate foo3; + extern crate foo4; + + pub fn foo() { + foo::foo(); + foo1::foo1(); + foo2::foo2(); + foo3::foo3(); + foo4::foo4(); + } + ", + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "pub fn foo4() {}") + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn rename_and_patch() { + Package::new("foo", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { version = "0.1", package = "foo" } + + [patch.crates-io] + foo = { path = "foo" } + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::foo(); }", + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn rename_twice() { + Package::new("foo", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { version = "0.1", package = "foo" } + [build-dependencies] + foo = { version = "0.1" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.1.0 (registry `dummy-registry`) +[ERROR] the crate `test v0.1.0 ([ROOT]/foo)` depends on crate `foo v0.1.0` multiple times with different names + +"#]]) + .run(); +} + +#[cargo_test] +fn rename_affects_fingerprint() { + Package::new("foo", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { version = "0.1", package = "foo" } + "#, + ) + .file("src/lib.rs", "extern crate foo;") + .build(); + + p.cargo("build -v").run(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { version = "0.1", package = "foo" } + "#, + ); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[FRESH] foo v0.1.0 +[DIRTY] test v0.1.0 ([ROOT]/foo): name of dependency changed (foo => bar) +[COMPILING] test v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..]` +error[E0463]: can't find crate for `foo` +... +"#]]) + .run(); +} + +#[cargo_test] +fn can_run_doc_tests() { + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.2.0").publish(); + + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { version = "0.1.0" } + baz = { version = "0.2.0", package = "bar" } + "#, + ) + .file( + "src/lib.rs", + " + extern crate bar; + extern crate baz; + ", + ) + .build(); + + foo.cargo("test -v").with_stderr_data(str![[r#" +... +[DOCTEST] foo +[RUNNING] `rustdoc [..]--test src/lib.rs [..] --extern bar=[ROOT]/foo/target/debug/deps/libbar-[HASH].rlib --extern baz=[ROOT]/foo/target/debug/deps/libbar-[HASH].rlib [..]` + +"#]]).run(); +} + +#[cargo_test] +fn features_still_work() { + Package::new("foo", "0.1.0").publish(); + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + p1 = { path = 'a', features = ['b'] } + p2 = { path = 'b' } + "#, + ) + .file("src/lib.rs", "") + .file( + "a/Cargo.toml", + r#" + [package] + name = "p1" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + b = { version = "0.1", package = "foo", optional = true } + "#, + ) + .file("a/src/lib.rs", "extern crate b;") + .file( + "b/Cargo.toml", + r#" + [package] + name = "p2" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + b = { version = "0.1", package = "bar", optional = true } + + [features] + default = ['b'] + "#, + ) + .file("b/src/lib.rs", "extern crate b;") + .build(); + + p.cargo("build -v").run(); +} + +#[cargo_test] +fn features_not_working() { + Package::new("foo", "0.1.0").publish(); + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + a = { path = 'a', package = 'p1', optional = true } + + [features] + default = ['p1'] + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("p1", "0.1.0")) + .build(); + + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `default` includes `p1` which is neither a dependency nor another feature + +"#]]) + .run(); +} + +#[cargo_test] +fn rename_with_dash() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "qwerty" + version = "0.1.0" + edition = "2015" + + [dependencies] + foo-bar = { path = 'a', package = 'a' } + "#, + ) + .file("src/lib.rs", "extern crate foo_bar;") + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("build").run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/replace.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/replace.rs new file mode 100644 index 000000000..e80341d93 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/replace.rs @@ -0,0 +1,1500 @@ +//! Tests for `[replace]` table source replacement. + +use cargo_test_support::git; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{basic_manifest, project, str}; + +#[cargo_test] +fn override_simple() { + Package::new("bar", "0.1.0").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" + edition = "2015" + 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_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn override_with_features() { + Package::new("bar", "0.1.0").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" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = {{ git = '{}', features = ["some_feature"] }} + "#, + bar.url() + ), + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 2 packages to latest compatible versions +[WARNING] replacement for `bar` uses the features mechanism. default-features and features will not take effect because the replacement dependency does not support this mechanism +[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn override_with_setting_default_features() { + Package::new("bar", "0.1.0").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" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = {{ git = '{}', default-features = false, features = ["none_default_feature"] }} + "#, + bar.url() + ), + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 2 packages to latest compatible versions +[WARNING] replacement for `bar` uses the features mechanism. default-features and features will not take effect because the replacement dependency does not support this mechanism +[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn missing_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + bar = { git = 'https://example.com' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").with_status(101).with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + replacements must specify a version to replace, but `https://github.com/rust-lang/crates.io-index#bar` does not + +"#]]).run(); +} + +#[cargo_test] +fn invalid_semver_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + + [replace] + "bar:*" = { git = 'https://example.com' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + replacements must specify a valid semver version to replace, but `bar:*` does not +... +"#]]) + .run(); +} + +#[cargo_test] +fn different_version() { + Package::new("bar", "0.2.0").publish(); + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = "0.2.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").with_status(101).with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + replacements cannot specify a version requirement, but found one for `https://github.com/rust-lang/crates.io-index#bar@0.1.0` + +"#]]).run(); +} + +#[cargo_test] +fn transitive() { + Package::new("bar", "0.1.0").publish(); + Package::new("baz", "0.2.0") + .dep("bar", "0.1.0") + .file("src/lib.rs", "extern crate bar; fn baz() { bar::bar(); }") + .publish(); + + let foo = 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" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.2.0" + + [replace] + "bar:0.1.0" = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.2.0 (registry `dummy-registry`) +[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..]) +[CHECKING] baz v0.2.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn persists_across_rebuilds() { + Package::new("bar", "0.1.0").publish(); + + let foo = 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" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn replace_registry_with_path() { + Package::new("bar", "0.1.0").publish(); + + let _ = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn bar() {}") + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = { path = "../bar" } + "#, + ) + .file( + "src/lib.rs", + "extern crate bar; pub fn foo() { bar::bar(); }", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.1.0 ([ROOT]/bar) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn use_a_spec_to_select() { + Package::new("baz", "0.1.1") + .file("src/lib.rs", "pub fn baz1() {}") + .publish(); + Package::new("baz", "0.2.0").publish(); + Package::new("bar", "0.1.1") + .dep("baz", "0.2") + .file( + "src/lib.rs", + "extern crate baz; pub fn bar() { baz::baz3(); }", + ) + .publish(); + + let foo = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("baz", "0.2.0")) + .file("src/lib.rs", "pub fn baz3() {}") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + baz = "0.1" + + [replace] + "baz:0.2.0" = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file( + "src/lib.rs", + " + extern crate bar; + extern crate baz; + + pub fn local() { + baz::baz1(); + bar::bar(); + } + ", + ) + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 4 packages to latest compatible versions +[ADDING] baz v0.1.1 (available: v0.2.0) +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.1 (registry `dummy-registry`) +[DOWNLOADED] bar v0.1.1 (registry `dummy-registry`) +[CHECKING] baz v0.2.0 ([ROOTURL]/override#[..]) +[CHECKING] baz v0.1.1 +[CHECKING] bar v0.1.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn override_adds_some_deps() { + Package::new("baz", "0.1.1").publish(); + Package::new("bar", "0.1.0").publish(); + + let foo = git::repo(&paths::root().join("override")) + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + + [replace] + "bar:0.1.0" = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] baz v0.1.1 (registry `dummy-registry`) +[CHECKING] baz v0.1.1 +[CHECKING] bar v0.1.0 ([ROOTURL]/override#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + Package::new("baz", "0.1.2").publish(); + p.cargo("update") + .arg(&format!("{}#bar", foo.url())) + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/override` +[UPDATING] `dummy-registry` index +[LOCKING] 0 packages to latest compatible versions +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]]) + .run(); + p.cargo("update https://github.com/rust-lang/crates.io-index#bar") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 0 packages to latest compatible versions +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]]) + .run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn locked_means_locked_yes_no_seriously_i_mean_locked() { + // this in theory exercises #2041 + Package::new("baz", "0.1.0").publish(); + Package::new("baz", "0.2.0").publish(); + Package::new("bar", "0.1.0").publish(); + + let foo = git::repo(&paths::root().join("override")) + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = "*" + "#, + ) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + baz = "0.1" + + [replace] + "bar:0.1.0" = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn override_wrong_name() { + Package::new("baz", "0.1.0").publish(); + + let foo = git::repo(&paths::root().join("override")) + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + baz = "0.1" + + [replace] + "baz:0.1.0" = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[ERROR] failed to get `baz` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + no matching package for override `https://github.com/rust-lang/crates.io-index#baz@0.1.0` found + location searched: [ROOTURL]/override + version required: =0.1.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn override_with_nothing() { + Package::new("bar", "0.1.0").publish(); + + let foo = git::repo(&paths::root().join("override")) + .file("src/lib.rs", "") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + + [replace] + "bar:0.1.0" = {{ git = '{}' }} + "#, + foo.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update [ROOTURL]/override + +Caused by: + Could not find Cargo.toml in `[ROOT]/home/.cargo/git/checkouts/override-[HASH]/[..]` + +"#]]) + .run(); +} + +#[cargo_test] +fn override_wrong_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [replace] + "bar:0.1.0" = { git = 'https://example.com', version = '0.2.0' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").with_status(101).with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + replacements cannot specify a version requirement, but found one for `https://github.com/rust-lang/crates.io-index#bar@0.1.0` + +"#]]).run(); +} + +#[cargo_test] +fn multiple_specs() { + Package::new("bar", "0.1.0").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" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = {{ git = '{0}' }} + + [replace."https://github.com/rust-lang/crates.io-index#bar:0.1.0"] + git = '{0}' + "#, + bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/foo)` + +Caused by: + overlapping replacement specifications found: + + * https://github.com/rust-lang/crates.io-index#bar@0.1.0 + * https://github.com/rust-lang/crates.io-index#bar@0.1.0 + + both specifications match: bar v0.1.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn test_override_dep() { + Package::new("bar", "0.1.0").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" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = {{ git = '{0}' }} + "#, + bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("test -p bar") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 2 packages to latest compatible versions +[ERROR] There are multiple `bar` packages in your project, and the specification `bar` is ambiguous. +Please re-run this command with one of the following specifications: + registry+https://github.com/rust-lang/crates.io-index#bar@0.1.0 + git+[ROOTURL]/override#bar@0.1.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn update() { + Package::new("bar", "0.1.0").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" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = {{ git = '{0}' }} + "#, + bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + p.cargo("update") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 0 packages to latest compatible versions + +"#]]) + .run(); +} + +// foo -> near -> far +// near is overridden with itself +#[cargo_test] +fn no_override_self() { + let deps = git::repo(&paths::root().join("override")) + .file("far/Cargo.toml", &basic_manifest("far", "0.1.0")) + .file("far/src/lib.rs", "") + .file( + "near/Cargo.toml", + r#" + [package] + name = "near" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + far = { path = "../far" } + "#, + ) + .file("near/src/lib.rs", "#![no_std] pub extern crate far;") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + near = {{ git = '{0}' }} + + [replace] + "near:0.1.0" = {{ git = '{0}' }} + "#, + deps.url() + ), + ) + .file("src/lib.rs", "#![no_std] pub extern crate near;") + .build(); + + p.cargo("check --verbose").run(); +} + +#[cargo_test] +fn override_an_override() { + Package::new("chrono", "0.2.0") + .dep("serde", "< 0.9") + .publish(); + Package::new("serde", "0.7.0") + .file("src/lib.rs", "pub fn serde07() {}") + .publish(); + Package::new("serde", "0.8.0") + .file("src/lib.rs", "pub fn serde08() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + chrono = "0.2" + serde = "0.8" + + [replace] + "chrono:0.2.0" = { path = "chrono" } + "serde:0.8.0" = { path = "serde" } + "#, + ) + .file( + "Cargo.lock", + r#" + [[package]] + name = "foo" + version = "0.0.1" + dependencies = [ + "chrono 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "chrono" + version = "0.2.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + replace = "chrono 0.2.0" + + [[package]] + name = "chrono" + version = "0.2.0" + dependencies = [ + "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "serde" + version = "0.7.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + + [[package]] + name = "serde" + version = "0.8.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + replace = "serde 0.8.0" + + [[package]] + name = "serde" + version = "0.8.0" + "#, + ) + .file( + "src/lib.rs", + " + extern crate chrono; + extern crate serde; + + pub fn foo() { + chrono::chrono(); + serde::serde08_override(); + } + ", + ) + .file( + "chrono/Cargo.toml", + r#" + [package] + name = "chrono" + version = "0.2.0" + edition = "2015" + authors = [] + + [dependencies] + serde = "< 0.9" + "#, + ) + .file( + "chrono/src/lib.rs", + " + extern crate serde; + pub fn chrono() { + serde::serde07(); + } + ", + ) + .file("serde/Cargo.toml", &basic_manifest("serde", "0.8.0")) + .file("serde/src/lib.rs", "pub fn serde08_override() {}") + .build(); + + p.cargo("check -v").run(); +} + +#[cargo_test] +fn overriding_nonexistent_no_spurious() { + Package::new("bar", "0.1.0").dep("baz", "0.1").publish(); + Package::new("baz", "0.1.0").publish(); + + let bar = git::repo(&paths::root().join("override")) + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "baz" } + "#, + ) + .file("src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = {{ git = '{url}' }} + "baz:0.1.0" = {{ git = '{url}' }} + "#, + url = bar.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] package replacement is not used: https://github.com/rust-lang/crates.io-index#baz@0.1.0 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn no_warnings_when_replace_is_used_in_another_workspace_member() { + Package::new("bar", "0.1.0").publish(); + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = [ "first_crate", "second_crate"] + + [replace] + "bar:0.1.0" = { path = "local_bar" } + "#, + ) + .file( + "first_crate/Cargo.toml", + r#" + [package] + name = "first_crate" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("first_crate/src/lib.rs", "") + .file( + "second_crate/Cargo.toml", + &basic_manifest("second_crate", "0.1.0"), + ) + .file("second_crate/src/lib.rs", "") + .file("local_bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("local_bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .cwd("first_crate") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.1.0 ([ROOT]/foo/local_bar) +[CHECKING] first_crate v0.1.0 ([ROOT]/foo/first_crate) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .cwd("second_crate") + .with_stdout_data("") + .with_stderr_data(str![[r#" +[CHECKING] second_crate v0.1.0 ([ROOT]/foo/second_crate) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn replace_to_path_dep() { + Package::new("bar", "0.1.0").dep("baz", "0.1").publish(); + Package::new("baz", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1.0" + + [replace] + "bar:0.1.0" = { path = "bar" } + "#, + ) + .file("src/lib.rs", "extern crate bar;") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "baz" } + "#, + ) + .file( + "bar/src/lib.rs", + "extern crate baz; pub fn bar() { baz::baz(); }", + ) + .file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("bar/baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn override_with_default_feature() { + Package::new("another", "0.1.0").publish(); + Package::new("another", "0.1.1").dep("bar", "0.1").publish(); + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar", default-features = false } + another = "0.1" + another2 = { path = "another2" } + + [replace] + 'bar:0.1.0' = { path = "bar" } + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::bar(); }") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = [] + "#, + ) + .file( + "bar/src/lib.rs", + r#" + #[cfg(feature = "default")] + pub fn bar() {} + "#, + ) + .file( + "another2/Cargo.toml", + r#" + [package] + name = "another2" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { version = "0.1", default-features = false } + "#, + ) + .file("another2/src/lib.rs", "") + .build(); + + p.cargo("run").run(); +} + +#[cargo_test] +fn override_plus_dep() { + Package::new("bar", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "0.1" + + [replace] + 'bar:0.1.0' = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = ".." } + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] cyclic package dependency: package `bar v0.1.0 ([ROOT]/foo/bar)` depends on itself. Cycle: +package `bar v0.1.0 ([ROOT]/foo/bar)` + ... which satisfies dependency `bar = "^0.1"` of package `foo v0.0.1 ([ROOT]/foo)` + ... which satisfies path dependency `foo` of package `bar v0.1.0 ([ROOT]/foo/bar)` + +"#]]) + .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" + edition = "2015" + 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_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([ROOT]/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" + edition = "2015" + 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_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[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 ([ROOT]/foo) +error[E0425]: cannot find function `bar`[..] +... +[ERROR] could not compile `foo` (lib) due to 1 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" + edition = "2015" + 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_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] git repository `[ROOTURL]/override` +[LOCKING] 2 packages to latest compatible versions +[CHECKING] bar v0.1.0+a ([ROOTURL]/override#[..]) +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/required_features.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/required_features.rs new file mode 100644 index 000000000..ea6357250 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/required_features.rs @@ -0,0 +1,1630 @@ +//! Tests for targets with `required-features`. + +use cargo_test_support::install::{assert_has_installed_exe, assert_has_not_installed_exe}; +use cargo_test_support::is_nightly; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn build_bin_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a"] + a = [] + + [[bin]] + name = "foo" + required-features = ["a"] + "#, + ) + .file( + "src/main.rs", + r#" + extern crate foo; + + #[cfg(feature = "a")] + fn test() { + foo::foo(); + } + + fn main() {} + "#, + ) + .file("src/lib.rs", r#"#[cfg(feature = "a")] pub fn foo() {}"#) + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + + p.cargo("build --no-default-features").run(); + + p.cargo("build --bin=foo").run(); + assert!(p.bin("foo").is_file()); + + p.cargo("build --bin=foo --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo` in package `foo` requires the features: `a` +Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); +} + +#[cargo_test] +fn build_bin_arg_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + + [[bin]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build --features a").run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn build_bin_multiple_required_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[bin]] + name = "foo_1" + path = "src/foo_1.rs" + required-features = ["b", "c"] + + [[bin]] + name = "foo_2" + path = "src/foo_2.rs" + required-features = ["a"] + "#, + ) + .file("src/foo_1.rs", "fn main() {}") + .file("src/foo_2.rs", "fn main() {}") + .build(); + + p.cargo("build").run(); + + assert!(!p.bin("foo_1").is_file()); + assert!(p.bin("foo_2").is_file()); + + p.cargo("build --features c").run(); + + assert!(p.bin("foo_1").is_file()); + assert!(p.bin("foo_2").is_file()); + + p.cargo("build --no-default-features").run(); +} + +#[cargo_test] +fn build_example_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a"] + a = [] + + [[example]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("examples/foo.rs", "fn main() {}") + .build(); + + p.cargo("build --example=foo").run(); + assert!(p.bin("examples/foo").is_file()); + + p.cargo("build --example=foo --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo` in package `foo` requires the features: `a` +Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); +} + +#[cargo_test] +fn build_example_arg_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + + [[example]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("examples/foo.rs", "fn main() {}") + .build(); + + p.cargo("build --example=foo --features a").run(); + assert!(p.bin("examples/foo").is_file()); +} + +#[cargo_test] +fn build_example_multiple_required_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[example]] + name = "foo_1" + required-features = ["b", "c"] + + [[example]] + name = "foo_2" + required-features = ["a"] + "#, + ) + .file("examples/foo_1.rs", "fn main() {}") + .file("examples/foo_2.rs", "fn main() {}") + .build(); + + p.cargo("build --example=foo_1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo_1` in package `foo` requires the features: `b`, `c` +Consider enabling them by passing, e.g., `--features="b c"` + +"#]]) + .run(); + p.cargo("build --example=foo_2").run(); + + assert!(!p.bin("examples/foo_1").is_file()); + assert!(p.bin("examples/foo_2").is_file()); + + p.cargo("build --example=foo_1 --features c").run(); + p.cargo("build --example=foo_2 --features c").run(); + + assert!(p.bin("examples/foo_1").is_file()); + assert!(p.bin("examples/foo_2").is_file()); + + p.cargo("build --example=foo_1 --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo_1` in package `foo` requires the features: `b`, `c` +Consider enabling them by passing, e.g., `--features="b c"` + +"#]]) + .run(); + p.cargo("build --example=foo_2 --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo_2` in package `foo` requires the features: `a` +Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); +} + +#[cargo_test] +fn test_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a"] + a = [] + + [[test]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("tests/foo.rs", "#[test]\nfn test() {}") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("test --no-default-features") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + p.cargo("test --test=foo") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("test --test=foo --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo` in package `foo` requires the features: `a` +Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); +} + +#[cargo_test] +fn test_arg_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + + [[test]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("tests/foo.rs", "#[test]\nfn test() {}") + .build(); + + p.cargo("test --features a") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test] +fn test_multiple_required_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[test]] + name = "foo_1" + required-features = ["b", "c"] + + [[test]] + name = "foo_2" + required-features = ["a"] + "#, + ) + .file("tests/foo_1.rs", "#[test]\nfn test() {}") + .file("tests/foo_2.rs", "#[test]\nfn test() {}") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo_2.rs (target/debug/deps/foo_2-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("test --features c") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo_1.rs (target/debug/deps/foo_1-[HASH][EXE]) +[RUNNING] tests/foo_2.rs (target/debug/deps/foo_2-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("test --no-default-features") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a"] + a = [] + + [[bench]] + name = "foo" + required-features = ["a"] + "#, + ) + .file( + "benches/foo.rs", + r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + } + "#, + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("bench --no-default-features") + .with_stderr_data(str![[r#" +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + p.cargo("bench --bench=foo") + .with_stderr_data(str![[r#" +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("bench --bench=foo --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo` in package `foo` requires the features: `a` +Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_arg_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + + [[bench]] + name = "foo" + required-features = ["a"] + "#, + ) + .file( + "benches/foo.rs", + r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + } + "#, + ) + .build(); + + p.cargo("bench --features a") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "bench")] +fn bench_multiple_required_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[bench]] + name = "foo_1" + required-features = ["b", "c"] + + [[bench]] + name = "foo_2" + required-features = ["a"] + "#, + ) + .file( + "benches/foo_1.rs", + r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + } + "#, + ) + .file( + "benches/foo_2.rs", + r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + } + "#, + ) + .build(); + + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo_2.rs (target/release/deps/foo_2-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("bench --features c") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo_1.rs (target/release/deps/foo_1-[HASH][EXE]) +[RUNNING] benches/foo_2.rs (target/release/deps/foo_2-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("bench --no-default-features") + .with_stderr_data(str![[r#" +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); +} + +#[cargo_test] +fn install_default_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a"] + a = [] + + [[bin]] + name = "foo" + required-features = ["a"] + + [[example]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("examples/foo.rs", "fn main() {}") + .build(); + + p.cargo("install --path .").run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + p.cargo("uninstall foo").run(); + + p.cargo("install --path . --no-default-features") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[WARNING] none of the package's binaries are available for install using the selected features + bin "foo" requires the features: `a` + example "foo" requires the features: `a` +Consider enabling some of the needed features by passing, e.g., `--features="a"` + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + + p.cargo("install --path . --bin=foo").run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + p.cargo("uninstall foo").run(); + + p.cargo("install --path . --bin=foo --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to compile `foo v0.0.1 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`. +To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path. + +Caused by: + target `foo` in package `foo` requires the features: `a` + Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + + p.cargo("install --path . --example=foo").run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + p.cargo("uninstall foo").run(); + + p.cargo("install --path . --example=foo --no-default-features") + .with_status(101) + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[ERROR] failed to compile `foo v0.0.1 ([ROOT]/foo)`, intermediate artifacts can be found at `[ROOT]/foo/target`. +To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path. + +Caused by: + target `foo` in package `foo` requires the features: `a` + Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); +} + +#[cargo_test] +fn install_arg_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + + [[bin]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("install --features a").run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + p.cargo("uninstall foo").run(); +} + +#[cargo_test] +fn install_multiple_required_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a", "b"] + a = [] + b = ["a"] + c = [] + + [[bin]] + name = "foo_1" + path = "src/foo_1.rs" + required-features = ["b", "c"] + + [[bin]] + name = "foo_2" + path = "src/foo_2.rs" + required-features = ["a"] + + [[example]] + name = "foo_3" + path = "src/foo_3.rs" + required-features = ["b", "c"] + + [[example]] + name = "foo_4" + path = "src/foo_4.rs" + required-features = ["a"] + "#, + ) + .file("src/foo_1.rs", "fn main() {}") + .file("src/foo_2.rs", "fn main() {}") + .file("src/foo_3.rs", "fn main() {}") + .file("src/foo_4.rs", "fn main() {}") + .build(); + + p.cargo("install --path .").run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo_1"); + assert_has_installed_exe(paths::cargo_home(), "foo_2"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_3"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_4"); + p.cargo("uninstall foo").run(); + + p.cargo("install --path . --bins --examples").run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo_1"); + assert_has_installed_exe(paths::cargo_home(), "foo_2"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_3"); + assert_has_installed_exe(paths::cargo_home(), "foo_4"); + p.cargo("uninstall foo").run(); + + p.cargo("install --path . --features c").run(); + assert_has_installed_exe(paths::cargo_home(), "foo_1"); + assert_has_installed_exe(paths::cargo_home(), "foo_2"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_3"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_4"); + p.cargo("uninstall foo").run(); + + p.cargo("install --path . --features c --bins --examples") + .run(); + assert_has_installed_exe(paths::cargo_home(), "foo_1"); + assert_has_installed_exe(paths::cargo_home(), "foo_2"); + assert_has_installed_exe(paths::cargo_home(), "foo_3"); + assert_has_installed_exe(paths::cargo_home(), "foo_4"); + p.cargo("uninstall foo").run(); + + p.cargo("install --path . --no-default-features") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[WARNING] none of the package's binaries are available for install using the selected features + bin "foo_1" requires the features: `b`, `c` + bin "foo_2" requires the features: `a` + example "foo_3" requires the features: `b`, `c` + example "foo_4" requires the features: `a` +Consider enabling some of the needed features by passing, e.g., `--features="b c"` + +"#]]) + .run(); + p.cargo("install --path . --no-default-features --bins") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[WARNING] target filter `bins` specified, but no targets matched; this is a no-op +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[WARNING] none of the package's binaries are available for install using the selected features + bin "foo_1" requires the features: `b`, `c` + bin "foo_2" requires the features: `a` + example "foo_3" requires the features: `b`, `c` + example "foo_4" requires the features: `a` +Consider enabling some of the needed features by passing, e.g., `--features="b c"` + +"#]]) + .run(); + p.cargo("install --path . --no-default-features --examples") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[WARNING] target filter `examples` specified, but no targets matched; this is a no-op +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[WARNING] none of the package's binaries are available for install using the selected features + bin "foo_1" requires the features: `b`, `c` + bin "foo_2" requires the features: `a` + example "foo_3" requires the features: `b`, `c` + example "foo_4" requires the features: `a` +Consider enabling some of the needed features by passing, e.g., `--features="b c"` + +"#]]) + .run(); + p.cargo("install --path . --no-default-features --bins --examples") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[WARNING] target filters `bins`, `examples` specified, but no targets matched; this is a no-op +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[WARNING] none of the package's binaries are available for install using the selected features + bin "foo_1" requires the features: `b`, `c` + bin "foo_2" requires the features: `a` + example "foo_3" requires the features: `b`, `c` + example "foo_4" requires the features: `a` +Consider enabling some of the needed features by passing, e.g., `--features="b c"` + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo_1"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_2"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_3"); + assert_has_not_installed_exe(paths::cargo_home(), "foo_4"); +} + +#[cargo_test] +fn dep_feature_in_toml() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar", features = ["a"] } + + [[bin]] + name = "foo" + required-features = ["bar/a"] + + [[example]] + name = "foo" + required-features = ["bar/a"] + + [[test]] + name = "foo" + required-features = ["bar/a"] + + [[bench]] + name = "foo" + required-features = ["bar/a"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("examples/foo.rs", "fn main() {}") + .file("tests/foo.rs", "#[test]\nfn test() {}") + .file( + "benches/foo.rs", + r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + + // bin + p.cargo("build --bin=foo").run(); + assert!(p.bin("foo").is_file()); + + // example + p.cargo("build --example=foo").run(); + assert!(p.bin("examples/foo").is_file()); + + // test + p.cargo("test --test=foo") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + // bench + if is_nightly() { + p.cargo("bench --bench=foo") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + } + + // install + p.cargo("install").run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + p.cargo("uninstall foo").run(); +} + +#[cargo_test] +fn dep_feature_in_cmd_line() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar" } + + [[bin]] + name = "foo" + required-features = ["bar/a"] + + [[example]] + name = "foo" + required-features = ["bar/a"] + + [[test]] + name = "foo" + required-features = ["bar/a"] + + [[bench]] + name = "foo" + required-features = ["bar/a"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("examples/foo.rs", "fn main() {}") + .file( + "tests/foo.rs", + r#" + #[test] + fn bin_is_built() { + let s = format!("target/debug/foo{}", std::env::consts::EXE_SUFFIX); + let p = std::path::Path::new(&s); + assert!(p.exists(), "foo does not exist"); + } + "#, + ) + .file( + "benches/foo.rs", + r#" + #![feature(test)] + extern crate test; + + #[bench] + fn bench(_: &mut test::Bencher) { + } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + // This is a no-op + p.cargo("build") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(!p.bin("foo").is_file()); + + // bin + p.cargo("build --bin=foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo` in package `foo` requires the features: `bar/a` +Consider enabling them by passing, e.g., `--features="bar/a"` + +"#]]) + .run(); + + p.cargo("build --bin=foo --features bar/a").run(); + assert!(p.bin("foo").is_file()); + + // example + p.cargo("build --example=foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo` in package `foo` requires the features: `bar/a` +Consider enabling them by passing, e.g., `--features="bar/a"` + +"#]]) + .run(); + + p.cargo("build --example=foo --features bar/a").run(); + assert!(p.bin("examples/foo").is_file()); + + // test + // This is a no-op, since no tests are enabled + p.cargo("test") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + // Delete the target directory so this can check if the main.rs gets built. + p.build_dir().rm_rf(); + p.cargo("test --test=foo --features bar/a") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bin_is_built ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + // bench + if is_nightly() { + p.cargo("bench") + .with_stderr_data(str![[r#" +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .with_stdout_data("") + .run(); + + p.cargo("bench --bench=foo --features bar/a") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test bench ... bench: [AVG_ELAPSED] ns/iter (+/- [JITTER]) + +test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + } + + // install + p.cargo("install --path .") + .with_stderr_data(str![[r#" +[INSTALLING] foo v0.0.1 ([ROOT]/foo) +[LOCKING] 1 package to latest compatible version +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[WARNING] none of the package's binaries are available for install using the selected features + bin "foo" requires the features: `bar/a` + example "foo" requires the features: `bar/a` +Consider enabling some of the needed features by passing, e.g., `--features="bar/a"` + +"#]]) + .run(); + assert_has_not_installed_exe(paths::cargo_home(), "foo"); + + p.cargo("install --features bar/a").run(); + assert_has_installed_exe(paths::cargo_home(), "foo"); + p.cargo("uninstall foo").run(); +} + +#[cargo_test] +fn test_skips_compiling_bin_with_missing_required_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + a = [] + + [[bin]] + name = "bin_foo" + path = "src/bin/foo.rs" + required-features = ["a"] + "#, + ) + .file("src/bin/foo.rs", "extern crate bar; fn main() {}") + .file("tests/foo.rs", "") + .file("benches/foo.rs", "") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("test --features a -j 1") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +error[E0463]: can't find crate for `bar` +... +"#]]) + .run(); + + if is_nightly() { + p.cargo("bench") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] benches/foo.rs (target/release/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("bench --features a -j 1") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +error[E0463]: can't find crate for `bar` +... +"#]]) + .run(); + } +} + +#[cargo_test] +fn run_default() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = [] + a = [] + + [[bin]] + name = "foo" + required-features = ["a"] + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "extern crate foo; fn main() {}") + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] target `foo` in package `foo` requires the features: `a` +Consider enabling them by passing, e.g., `--features="a"` + +"#]]) + .run(); + + p.cargo("run --features a").run(); +} + +#[cargo_test] +fn run_default_multiple_required_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + default = ["a"] + a = [] + b = [] + + [[bin]] + name = "foo1" + path = "src/foo1.rs" + required-features = ["a"] + + [[bin]] + name = "foo3" + path = "src/foo3.rs" + required-features = ["b"] + + [[bin]] + name = "foo2" + path = "src/foo2.rs" + required-features = ["b"] + "#, + ) + .file("src/lib.rs", "") + .file("src/foo1.rs", "extern crate foo; fn main() {}") + .file("src/foo3.rs", "extern crate foo; fn main() {}") + .file("src/foo2.rs", "extern crate foo; fn main() {}") + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key. +available binaries: foo1, foo2, foo3 + +"#]]) + .run(); +} + +#[cargo_test] +fn renamed_required_features() { + // Test that required-features uses renamed package feature names. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [[bin]] + name = "x" + required-features = ["a1/f1"] + + [dependencies] + a1 = {path="a1", package="a"} + a2 = {path="a2", package="a"} + "#, + ) + .file( + "src/bin/x.rs", + r#" + fn main() { + a1::f(); + a2::f(); + } + "#, + ) + .file( + "a1/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + + [features] + f1 = [] + "#, + ) + .file( + "a1/src/lib.rs", + r#" + pub fn f() { + if cfg!(feature="f1") { + println!("a1 f1"); + } + } + "#, + ) + .file( + "a2/Cargo.toml", + r#" + [package] + name = "a" + version = "0.2.0" + + [features] + f2 = [] + "#, + ) + .file( + "a2/src/lib.rs", + r#" + pub fn f() { + if cfg!(feature="f2") { + println!("a2 f2"); + } + } + "#, + ) + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[ERROR] target `x` in package `foo` requires the features: `a1/f1` +Consider enabling them by passing, e.g., `--features="a1/f1"` + +"#]]) + .run(); + + p.cargo("build --features a1/f1").run(); + p.rename_run("x", "x_with_f1") + .with_stdout_data(str![[r#" +a1 f1 + +"#]]) + .run(); + + p.cargo("build --features a1/f1,a2/f2").run(); + p.rename_run("x", "x_with_f1_f2") + .with_stdout_data(str![[r#" +a1 f1 +a2 f2 + +"#]]) + .run(); +} + +#[cargo_test] +fn truncated_install_warning_message() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [features] + feature1 = [] + feature2 = [] + feature3 = [] + feature4 = [] + feature5 = [] + + [[bin]] + name = "foo1" + required-features = ["feature1", "feature2", "feature3"] + + [[bin]] + name = "foo2" + required-features = ["feature2"] + + [[bin]] + name = "foo3" + required-features = ["feature3"] + + [[bin]] + name = "foo4" + required-features = ["feature4", "feature1"] + + [[bin]] + name = "foo5" + required-features = ["feature1", "feature2", "feature3", "feature4", "feature5"] + + [[bin]] + name = "foo6" + required-features = ["feature1", "feature2", "feature3", "feature4", "feature5"] + + [[bin]] + name = "foo7" + required-features = ["feature1", "feature2", "feature3", "feature4", "feature5"] + + [[bin]] + name = "foo8" + required-features = ["feature1", "feature2", "feature3", "feature4", "feature5"] + + [[bin]] + name = "foo9" + required-features = ["feature1", "feature2", "feature3", "feature4", "feature5"] + + [[bin]] + name = "foo10" + required-features = ["feature1", "feature2", "feature3", "feature4", "feature5"] + + [[example]] + name = "example1" + required-features = ["feature1", "feature2"] + "#, + ) + .file("src/bin/foo1.rs", "fn main() {}") + .file("src/bin/foo2.rs", "fn main() {}") + .file("src/bin/foo3.rs", "fn main() {}") + .file("src/bin/foo4.rs", "fn main() {}") + .file("src/bin/foo5.rs", "fn main() {}") + .file("src/bin/foo6.rs", "fn main() {}") + .file("src/bin/foo7.rs", "fn main() {}") + .file("src/bin/foo8.rs", "fn main() {}") + .file("src/bin/foo9.rs", "fn main() {}") + .file("src/bin/foo10.rs", "fn main() {}") + .file("examples/example1.rs", "fn main() {}") + .build(); + + p.cargo("install --path .").with_stderr_data(str![[r#" +[INSTALLING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[WARNING] none of the package's binaries are available for install using the selected features + bin "foo1" requires the features: `feature1`, `feature2`, `feature3` + bin "foo10" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5` + bin "foo2" requires the features: `feature2` + bin "foo3" requires the features: `feature3` + bin "foo4" requires the features: `feature4`, `feature1` + bin "foo5" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5` + bin "foo6" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5` +4 more targets also requires features not enabled. See them in the Cargo.toml file. +Consider enabling some of the needed features by passing, e.g., `--features="feature1 feature2 feature3"` + +"#]]).run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/run.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/run.rs new file mode 100644 index 000000000..fa3e8fc5f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/run.rs @@ -0,0 +1,1744 @@ +//! Tests for the `cargo run` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::{ + basic_bin_manifest, basic_lib_manifest, basic_manifest, project, str, Project, +}; +use cargo_util::paths::dylib_path_envvar; + +#[cargo_test] +fn simple() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn quiet_arg() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("run -q") + .with_stderr_data("") + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); + + p.cargo("run --quiet") + .with_stderr_data("") + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[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_data(str![[r#" +[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_data(str![[r#" +[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"); }"#) + .build(); + + p.cargo("run -q -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot set both --verbose and --quiet + +"#]]) + .run(); +} + +#[cargo_test] +fn quiet_arg_and_verbose_config() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + verbose = true + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("run -q") + .with_stderr_data("") + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn verbose_arg_and_quiet_config() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + quiet = true + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("run -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn quiet_config_alone() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + quiet = true + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("run") + .with_stderr_data("") + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn verbose_config_alone() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + verbose = true + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn quiet_config_and_verbose_config() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [term] + verbose = true + quiet = true + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot set both `term.verbose` and `term.quiet` + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_with_args() { + let p = project() + .file( + "src/main.rs", + r#" + fn main() { + assert_eq!(std::env::args().nth(1).unwrap(), "hello"); + assert_eq!(std::env::args().nth(2).unwrap(), "world"); + } + "#, + ) + .build(); + + p.cargo("run hello world").run(); +} + +#[cfg(unix)] +#[cargo_test] +fn simple_with_non_utf8_args() { + use std::os::unix::ffi::OsStrExt; + + let p = project() + .file( + "src/main.rs", + r#" + use std::ffi::OsStr; + use std::os::unix::ffi::OsStrExt; + + fn main() { + assert_eq!(std::env::args_os().nth(1).unwrap(), OsStr::from_bytes(b"hello")); + assert_eq!(std::env::args_os().nth(2).unwrap(), OsStr::from_bytes(b"ab\xffcd")); + } + "#, + ) + .build(); + + p.cargo("run") + .arg("hello") + .arg(std::ffi::OsStr::from_bytes(b"ab\xFFcd")) + .run(); +} + +#[cargo_test] +fn exit_code() { + let p = project() + .file("src/main.rs", "fn main() { std::process::exit(2); }") + .build(); + + let expected = if !cfg!(unix) { + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` +[ERROR] process didn't exit successfully: `target/debug/foo[EXE]` ([EXIT_STATUS]: 2) + +"#]] + } else { + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo` + +"#]] + }; + p.cargo("run") + .with_status(2) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn exit_code_verbose() { + let p = project() + .file("src/main.rs", "fn main() { std::process::exit(2); }") + .build(); + + let expected = if !cfg!(unix) { + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` +[ERROR] process didn't exit successfully: `target/debug/foo[EXE]` ([EXIT_STATUS]: 2) + +"#]] + } else { + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]] + }; + + p.cargo("run -v") + .with_status(2) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test] +fn no_main_file() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] a bin target must be available for `cargo run` + +"#]]) + .run(); +} + +#[cargo_test] +fn too_many_bins() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "") + .file("src/bin/b.rs", "") + .build(); + + // Using [..] here because the order is not stable + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key. +available binaries: a, b + +"#]]) + .run(); +} + +#[cargo_test] +fn specify_name() { + let p = project() + .file("src/lib.rs", "") + .file( + "src/bin/a.rs", + r#" + #[allow(unused_extern_crates)] + extern crate foo; + fn main() { println!("hello a.rs"); } + "#, + ) + .file( + "src/bin/b.rs", + r#" + #[allow(unused_extern_crates)] + extern crate foo; + fn main() { println!("hello b.rs"); } + "#, + ) + .build(); + + p.cargo("run --bin a -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] src/lib.rs [..]` +[RUNNING] `rustc [..] src/bin/a.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/a[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello a.rs + +"#]]) + .run(); + + p.cargo("run --bin b -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] src/bin/b.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/b[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello b.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn specify_default_run() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + default-run = "a" + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/a.rs", r#"fn main() { println!("hello A"); }"#) + .file("src/bin/b.rs", r#"fn main() { println!("hello B"); }"#) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +hello A + +"#]]) + .run(); + p.cargo("run --bin a") + .with_stdout_data(str![[r#" +hello A + +"#]]) + .run(); + p.cargo("run --bin b") + .with_stdout_data(str![[r#" +hello B + +"#]]) + .run(); +} + +#[cargo_test] +fn bogus_default_run() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + default-run = "b" + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/a.rs", r#"fn main() { println!("hello A"); }"#) + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + default-run target `b` not found + + [HELP] a target with a similar name exists: `a` + +"#]]) + .run(); +} + +#[cargo_test] +fn run_example() { + let p = project() + .file("src/lib.rs", "") + .file("examples/a.rs", r#"fn main() { println!("example"); }"#) + .file("src/bin/a.rs", r#"fn main() { println!("bin"); }"#) + .build(); + + p.cargo("run --example a") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/examples/a[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +example + +"#]]) + .run(); +} + +#[cargo_test] +fn run_library_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + [[example]] + name = "bar" + crate-type = ["lib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/bar.rs", "fn foo() {}") + .build(); + + p.cargo("run --example bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] example target `bar` is a library and cannot be executed + +"#]]) + .run(); +} + +#[cargo_test] +fn run_bin_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + [[example]] + name = "bar" + crate-type = ["bin"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/bar.rs", r#"fn main() { println!("example"); }"#) + .build(); + + p.cargo("run --example bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/examples/bar[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +example + +"#]]) + .run(); +} + +fn autodiscover_examples_project(rust_edition: &str, autoexamples: Option) -> Project { + let autoexamples = match autoexamples { + None => "".to_string(), + Some(bool) => format!("autoexamples = {}", bool), + }; + project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + edition = "{rust_edition}" + {autoexamples} + + [features] + magic = [] + + [[example]] + name = "do_magic" + required-features = ["magic"] + "#, + rust_edition = rust_edition, + autoexamples = autoexamples + ), + ) + .file("examples/a.rs", r#"fn main() { println!("example"); }"#) + .file( + "examples/do_magic.rs", + r#" + fn main() { println!("magic example"); } + "#, + ) + .build() +} + +#[cargo_test] +fn run_example_autodiscover_2015() { + let p = autodiscover_examples_project("2015", None); + p.cargo("run --example a") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] An explicit [[example]] section is specified in Cargo.toml which currently +disables Cargo from automatically inferring other example targets. +This inference behavior will change in the Rust 2018 edition and the following +files will be included as a example target: + +* examples/a.rs + +This is likely to break cargo build or cargo test as these files may not be +ready to be compiled as a example target today. You can future-proof yourself +and disable this warning by adding `autoexamples = false` to your [package] +section. You may also move the files to a location where Cargo would not +automatically infer them to be a target, such as in subfolders. + +For more information on this warning you can consult +https://github.com/rust-lang/cargo/issues/5330 +[ERROR] no example target named `a`. +Available example targets: + do_magic + + +"#]]) + .run(); +} + +#[cargo_test] +fn run_example_autodiscover_2015_with_autoexamples_enabled() { + let p = autodiscover_examples_project("2015", Some(true)); + p.cargo("run --example a") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/examples/a[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +example + +"#]]) + .run(); +} + +#[cargo_test] +fn run_example_autodiscover_2015_with_autoexamples_disabled() { + let p = autodiscover_examples_project("2015", Some(false)); + p.cargo("run --example a") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target named `a`. +Available example targets: + do_magic + + +"#]]) + .run(); +} + +#[cargo_test] +fn run_example_autodiscover_2018() { + let p = autodiscover_examples_project("2018", None); + p.cargo("run --example a") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/examples/a[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +example + +"#]]) + .run(); +} + +#[cargo_test] +fn autobins_disables() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + autobins = false + "#, + ) + .file("src/lib.rs", "pub mod bin;") + .file("src/bin/mod.rs", "// empty") + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] a bin target must be available for `cargo run` + +"#]]) + .run(); +} + +#[cargo_test] +fn run_bins() { + let p = project() + .file("src/lib.rs", "") + .file("examples/a.rs", r#"fn main() { println!("example"); }"#) + .file("src/bin/a.rs", r#"fn main() { println!("bin"); }"#) + .build(); + + p.cargo("run --bins") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] unexpected argument '--bins' found + + tip: a similar argument exists: '--bin' +... +"#]]) + .run(); +} + +#[cargo_test] +fn run_with_filename() { + let p = project() + .file("src/lib.rs", "") + .file( + "src/bin/a.rs", + r#" + extern crate foo; + fn main() { println!("hello a.rs"); } + "#, + ) + .file("examples/a.rs", r#"fn main() { println!("example"); }"#) + .build(); + + p.cargo("run --bin bin.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no bin target named `bin.rs`. +Available bin targets: + a + + +"#]]) + .run(); + + p.cargo("run --bin a.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no bin target named `a.rs` + +[HELP] a target with a similar name exists: `a` + +"#]]) + .run(); + + p.cargo("run --example example.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target named `example.rs`. +Available example targets: + a + + +"#]]) + .run(); + + p.cargo("run --example a.rs") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target named `a.rs` + +[HELP] a target with a similar name exists: `a` + +"#]]) + .run(); +} + +#[cargo_test] +fn either_name_or_example() { + let p = project() + .file("src/bin/a.rs", r#"fn main() { println!("hello a.rs"); }"#) + .file("examples/b.rs", r#"fn main() { println!("hello b.rs"); }"#) + .build(); + + p.cargo("run --bin a --example b") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` can run at most one executable, but multiple were specified + +"#]]) + .run(); +} + +#[cargo_test] +fn one_bin_multiple_examples() { + let p = project() + .file("src/lib.rs", "") + .file( + "src/bin/main.rs", + r#"fn main() { println!("hello main.rs"); }"#, + ) + .file("examples/a.rs", r#"fn main() { println!("hello a.rs"); }"#) + .file("examples/b.rs", r#"fn main() { println!("hello b.rs"); }"#) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/main[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello main.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn example_with_release_flag() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + version = "*" + path = "bar" + "#, + ) + .file( + "examples/a.rs", + r#" + extern crate bar; + + fn main() { + if cfg!(debug_assertions) { + println!("slow1") + } else { + println!("fast1") + } + bar::baz(); + } + "#, + ) + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file( + "bar/src/bar.rs", + r#" + pub fn baz() { + if cfg!(debug_assertions) { + println!("slow2") + } else { + println!("fast2") + } + } + "#, + ) + .build(); + + p.cargo("run -v --release --example a") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/bar.rs [..]--crate-type lib --emit=[..]link -C opt-level=3[..] -C metadata=[..] --out-dir [ROOT]/foo/target/release/deps -C strip=debuginfo -L dependency=[ROOT]/foo/target/release/deps` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name a --edition=2015 examples/a.rs [..]--crate-type bin --emit=[..]link -C opt-level=3[..] -C metadata=[..] --out-dir [ROOT]/foo/target/release/examples -C strip=debuginfo -L dependency=[ROOT]/foo/target/release/deps --extern bar=[ROOT]/foo/target/release/deps/libbar-[HASH].rlib` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `target/release/examples/a[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +fast1 +fast2 + +"#]]) + .run(); + + p.cargo("run -v --example a") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc --crate-name bar --edition=2015 bar/src/bar.rs [..]--crate-type lib --emit=[..]link [..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name a --edition=2015 examples/a.rs [..]--crate-type bin --emit=[..]link [..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/examples -L dependency=[ROOT]/foo/target/debug/deps --extern bar=[ROOT]/foo/target/debug/deps/libbar-[HASH].rlib` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/examples/a[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +slow1 +slow2 + +"#]]) + .run(); +} + +#[cargo_test] +fn run_dylib_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + "src/main.rs", + r#"extern crate bar; fn main() { bar::bar(); }"#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + authors = [] + + [lib] + name = "bar" + crate-type = ["dylib"] + "#, + ) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("run hello world").run(); +} + +#[cargo_test] +fn run_with_bin_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies.bar] + path = "bar" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "bar" + "#, + ) + .file("bar/src/main.rs", r#"fn main() { println!("bar"); }"#) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[WARNING] foo v0.0.1 ([ROOT]/foo) ignoring invalid dependency `bar` which is missing a lib target +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn run_with_bin_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies.bar1] + path = "bar1" + [dependencies.bar2] + path = "bar2" + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .file( + "bar1/Cargo.toml", + r#" + [package] + name = "bar1" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "bar1" + "#, + ) + .file("bar1/src/main.rs", r#"fn main() { println!("bar1"); }"#) + .file( + "bar2/Cargo.toml", + r#" + [package] + name = "bar2" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "bar2" + "#, + ) + .file("bar2/src/main.rs", r#"fn main() { println!("bar2"); }"#) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[WARNING] foo v0.0.1 ([ROOT]/foo) ignoring invalid dependency `bar1` which is missing a lib target +[WARNING] foo v0.0.1 ([ROOT]/foo) ignoring invalid dependency `bar2` which is missing a lib target +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn run_with_bin_dep_in_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo1", "foo2"] + "#, + ) + .file( + "foo1/Cargo.toml", + r#" + [package] + name = "foo1" + version = "0.0.1" + edition = "2015" + + [dependencies.bar1] + path = "bar1" + "#, + ) + .file("foo1/src/main.rs", r#"fn main() { println!("hello"); }"#) + .file( + "foo1/bar1/Cargo.toml", + r#" + [package] + name = "bar1" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "bar1" + "#, + ) + .file( + "foo1/bar1/src/main.rs", + r#"fn main() { println!("bar1"); }"#, + ) + .file( + "foo2/Cargo.toml", + r#" + [package] + name = "foo2" + version = "0.0.1" + edition = "2015" + + [dependencies.bar2] + path = "bar2" + "#, + ) + .file("foo2/src/main.rs", r#"fn main() { println!("hello"); }"#) + .file( + "foo2/bar2/Cargo.toml", + r#" + [package] + name = "bar2" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "bar2" + "#, + ) + .file( + "foo2/bar2/src/main.rs", + r#"fn main() { println!("bar2"); }"#, + ) + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key. +available binaries: bar1, bar2, foo1, foo2 + +"#]]) + .run(); + + p.cargo("run --bin foo1") + .with_stderr_data(str![[r#" +[WARNING] foo1 v0.0.1 ([ROOT]/foo/foo1) ignoring invalid dependency `bar1` which is missing a lib target +[WARNING] foo2 v0.0.1 ([ROOT]/foo/foo2) ignoring invalid dependency `bar2` which is missing a lib target +[COMPILING] foo1 v0.0.1 ([ROOT]/foo/foo1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo1[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn release_works() { + let p = project() + .file( + "src/main.rs", + r#" + fn main() { if cfg!(debug_assertions) { panic!() } } + "#, + ) + .build(); + + p.cargo("run --release") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `target/release/foo[EXE]` + +"#]]) + .run(); + assert!(p.release_bin("foo").is_file()); +} + +#[cargo_test] +fn release_short_works() { + let p = project() + .file( + "src/main.rs", + r#" + fn main() { if cfg!(debug_assertions) { panic!() } } + "#, + ) + .build(); + + p.cargo("run -r") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `target/release/foo[EXE]` + +"#]]) + .run(); + assert!(p.release_bin("foo").is_file()); +} + +#[cargo_test] +fn run_bin_different_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "bar" + "#, + ) + .file("src/bar.rs", "fn main() {}") + .build(); + + p.cargo("run").run(); +} + +#[cargo_test] +fn dashes_are_forwarded() { + let p = project() + .file( + "src/bin/bar.rs", + r#" + fn main() { + let s: Vec = std::env::args().collect(); + assert_eq!(s[1], "--"); + assert_eq!(s[2], "a"); + assert_eq!(s[3], "--"); + assert_eq!(s[4], "b"); + } + "#, + ) + .build(); + + p.cargo("run -- -- a -- b").run(); +} + +#[cargo_test] +fn run_from_executable_folder() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + let cwd = p.root().join("target").join("debug"); + p.cargo("build").run(); + + p.cargo("run") + .cwd(cwd) + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `./foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); +} + +#[cargo_test] +fn run_with_library_paths() { + let p = project(); + + // Only link search directories within the target output directory are + // propagated through to dylib_path_envvar() (see #3366). + let mut dir1 = p.target_debug_dir(); + dir1.push("foo\\backslash"); + + let mut dir2 = p.target_debug_dir(); + dir2.push("dir=containing=equal=signs"); + + let p = p + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + &format!( + r##" + fn main() {{ + println!(r#"cargo::rustc-link-search=native={}"#); + println!(r#"cargo::rustc-link-search={}"#); + }} + "##, + dir1.display(), + dir2.display() + ), + ) + .file( + "src/main.rs", + &format!( + r##" + fn main() {{ + let search_path = std::env::var_os("{}").unwrap(); + let paths = std::env::split_paths(&search_path).collect::>(); + println!("{{:#?}}", paths); + assert!(paths.contains(&r#"{}"#.into())); + assert!(paths.contains(&r#"{}"#.into())); + }} + "##, + dylib_path_envvar(), + dir1.display(), + dir2.display() + ), + ) + .build(); + + p.cargo("run").run(); +} + +#[cargo_test] +fn library_paths_sorted_alphabetically() { + let p = project(); + + let mut dir1 = p.target_debug_dir(); + dir1.push("zzzzzzz"); + + let mut dir2 = p.target_debug_dir(); + dir2.push("BBBBBBB"); + + let mut dir3 = p.target_debug_dir(); + dir3.push("aaaaaaa"); + + let p = p + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file( + "build.rs", + &format!( + r##" + fn main() {{ + println!(r#"cargo::rustc-link-search=native={}"#); + println!(r#"cargo::rustc-link-search=native={}"#); + println!(r#"cargo::rustc-link-search=native={}"#); + }} + "##, + dir1.display(), + dir2.display(), + dir3.display() + ), + ) + .file( + "src/main.rs", + &format!( + r##" + fn main() {{ + let search_path = std::env::var_os("{}").unwrap(); + let paths = std::env::split_paths(&search_path).collect::>(); + // ASCII case-sensitive sort + assert_eq!("BBBBBBB", paths[0].file_name().unwrap().to_string_lossy()); + assert_eq!("aaaaaaa", paths[1].file_name().unwrap().to_string_lossy()); + assert_eq!("zzzzzzz", paths[2].file_name().unwrap().to_string_lossy()); + }} + "##, + dylib_path_envvar() + ), + ) + .build(); + + p.cargo("run").run(); +} + +#[cargo_test] +fn fail_no_extra_verbose() { + let p = project() + .file("src/main.rs", "fn main() { std::process::exit(1); }") + .build(); + + p.cargo("run -q") + .with_status(1) + .with_stdout_data("") + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn run_multiple_packages() { + let p = project() + .no_manifest() + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace] + + [dependencies] + d1 = { path = "d1" } + d2 = { path = "d2" } + d3 = { path = "../d3" } # outside of the workspace + + [[bin]] + name = "foo" + "#, + ) + .file("foo/src/foo.rs", "fn main() { println!(\"foo\"); }") + .file("foo/d1/Cargo.toml", &basic_bin_manifest("d1")) + .file("foo/d1/src/lib.rs", "") + .file("foo/d1/src/main.rs", "fn main() { println!(\"d1\"); }") + .file("foo/d2/Cargo.toml", &basic_bin_manifest("d2")) + .file("foo/d2/src/main.rs", "fn main() { println!(\"d2\"); }") + .file("d3/Cargo.toml", &basic_bin_manifest("d3")) + .file("d3/src/main.rs", "fn main() { println!(\"d2\"); }") + .build(); + + let cargo = || { + let mut process_builder = p.cargo("run"); + process_builder.cwd("foo"); + process_builder + }; + + cargo() + .arg("-p") + .arg("d1") + .with_stdout_data(str![[r#" +d1 + +"#]]) + .run(); + + cargo() + .arg("-p") + .arg("d2") + .arg("--bin") + .arg("d2") + .with_stdout_data(str![[r#" +d2 + +"#]]) + .run(); + + cargo() + .with_stdout_data(str![[r#" +foo + +"#]]) + .run(); + + cargo() + .arg("-p") + .arg("d1") + .arg("-p") + .arg("d2") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--package []' cannot be used multiple times +... +"#]]) + .run(); + + cargo() + .arg("-p") + .arg("d3") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package(s) `d3` not found in workspace `[ROOT]/foo/foo` + +"#]]) + .run(); + + cargo() + .arg("-p") + .arg("d*") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` does not support glob pattern `d*` on package selection + +"#]]) + .run(); +} + +#[cargo_test] +fn explicit_bin_with_args() { + let p = project() + .file( + "src/main.rs", + r#" + fn main() { + assert_eq!(std::env::args().nth(1).unwrap(), "hello"); + assert_eq!(std::env::args().nth(2).unwrap(), "world"); + } + "#, + ) + .build(); + + p.cargo("run --bin foo hello world").run(); +} + +#[cargo_test] +fn run_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_bin_manifest("a")) + .file("a/src/main.rs", r#"fn main() {println!("run-a");}"#) + .file("b/Cargo.toml", &basic_bin_manifest("b")) + .file("b/src/main.rs", r#"fn main() {println!("run-b");}"#) + .build(); + + p.cargo("run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `cargo run` could not determine which binary to run. Use the `--bin` option to specify a binary, or the `default-run` manifest key. +available binaries: a, b + +"#]]) + .run(); + p.cargo("run --bin a") + .with_stdout_data(str![[r#" +run-a + +"#]]) + .run(); +} + +#[cargo_test] +fn default_run_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + edition = "2015" + default-run = "a" + "#, + ) + .file("a/src/main.rs", r#"fn main() {println!("run-a");}"#) + .file("b/Cargo.toml", &basic_bin_manifest("b")) + .file("b/src/main.rs", r#"fn main() {println!("run-b");}"#) + .build(); + + p.cargo("run") + .with_stdout_data(str![[r#" +run-a + +"#]]) + .run(); +} + +#[cargo_test] +fn print_env_verbose() { + let p = project() + .file("Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("src/main.rs", r#"fn main() {println!("run-a");}"#) + .build(); + + p.cargo("run -vv") + .with_stderr_data(str![[r#" +[COMPILING] a v0.0.1 ([ROOT]/foo) +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc --crate-name a[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] target/debug/a[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(target_os = "macos")] +fn run_link_system_path_macos() { + use cargo_test_support::paths; + use std::fs; + // Check that the default system library path is honored. + // First, build a shared library that will be accessed from + // DYLD_FALLBACK_LIBRARY_PATH. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + [lib] + crate-type = ["cdylib"] + "#, + ) + .file( + "src/lib.rs", + "#[no_mangle] pub extern fn something_shared() {}", + ) + .build(); + p.cargo("build").run(); + + // This is convoluted. Since this test can't modify things in /usr, + // this needs to dance around to check that things work. + // + // The default DYLD_FALLBACK_LIBRARY_PATH is: + // $(HOME)/lib:/usr/local/lib:/lib:/usr/lib + // + // This will make use of ~/lib in the path, but the default cc link + // path is /usr/lib:/usr/local/lib. So first need to build in one + // location, and then move it to ~/lib. + // + // 1. Build with rustc-link-search pointing to libfoo so the initial + // binary can be linked. + // 2. Move the library to ~/lib + // 3. Run `cargo run` to make sure it can still find the library in + // ~/lib. + // + // This should be equivalent to having the library in /usr/local/lib. + let p2 = project() + .at("bar") + .file("Cargo.toml", &basic_bin_manifest("bar")) + .file( + "src/main.rs", + r#" + extern { + fn something_shared(); + } + fn main() { + unsafe { something_shared(); } + } + "#, + ) + .file( + "build.rs", + &format!( + r#" + fn main() {{ + println!("cargo::rustc-link-lib=foo"); + println!("cargo::rustc-link-search={}"); + }} + "#, + p.target_debug_dir().display() + ), + ) + .build(); + p2.cargo("build").run(); + p2.cargo("test").run(); + + let libdir = paths::home().join("lib"); + fs::create_dir(&libdir).unwrap(); + fs::rename( + p.target_debug_dir().join("libfoo.dylib"), + libdir.join("libfoo.dylib"), + ) + .unwrap(); + p.root().rm_rf(); + const VAR: &str = "DYLD_FALLBACK_LIBRARY_PATH"; + // Reset DYLD_FALLBACK_LIBRARY_PATH so that we don't inherit anything that + // was set by the cargo that invoked the test. + p2.cargo("run").env_remove(VAR).run(); + p2.cargo("test").env_remove(VAR).run(); + // Ensure this still works when DYLD_FALLBACK_LIBRARY_PATH has + // a value set. + p2.cargo("run").env(VAR, &libdir).run(); + p2.cargo("test").env(VAR, &libdir).run(); +} + +#[cargo_test] +fn run_binary_with_same_name_as_dependency() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = "foo" } + "#, + ) + .file( + "src/main.rs", + r#" + fn main() {} + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [lib] + name = "foo" + path = "foo.rs" + "#, + ) + .file("foo/foo.rs", "") + .build(); + p.cargo("run").run(); + p.cargo("check -p foo@0.5.0").run(); + p.cargo("run -p foo@0.5.0").run(); + p.cargo("run -p foo@0.5").run(); + p.cargo("run -p foo@0.4") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package(s) `foo@0.4` not found in workspace `[ROOT]/foo` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rust_version.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rust_version.rs new file mode 100644 index 000000000..a007eb060 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rust_version.rs @@ -0,0 +1,1072 @@ +//! Tests for targets with `rust-version`. + +use cargo_test_support::prelude::*; +use cargo_test_support::{cargo_process, project, registry::Package, str}; + +#[cargo_test] +fn rust_version_satisfied() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + rust-version = "1.1.1" + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check").run(); + p.cargo("check --ignore-rust-version").run(); +} + +#[cargo_test] +fn rust_version_error() { + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + rust-version = "^1.43" + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build() + .cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] unexpected version requirement, expected a version like "1.32" + --> Cargo.toml:7:28 + | +7 | rust-version = "^1.43" + | ^^^^^^^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn rust_version_older_than_edition() { + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + rust-version = "1.1" + edition = "2018" + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build() + .cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + rust-version 1.1 is older than first version (1.31.0) required by the specified edition (2018) + +"#]]) + .run(); +} + +#[cargo_test] +fn lint_self_incompatible_with_rust_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + rust-version = "1.9876.0" + [[bin]] + name = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] rustc [..] is not supported by the following package: + foo@0.0.1 requires rustc 1.9876.0 + + +"#]]) + .run(); + p.cargo("check --ignore-rust-version").run(); +} + +#[cargo_test] +fn lint_dep_incompatible_with_rust_version() { + Package::new("too_new_parent", "0.0.1") + .dep("too_new_child", "0.0.1") + .rust_version("1.2345.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("too_new_child", "0.0.1") + .rust_version("1.2345.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("rustc_compatible", "0.0.1") + .rust_version("1.60.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + rust-version = "1.50" + authors = [] + [dependencies] + too_new_parent = "0.0.1" + rustc_compatible = "0.0.1" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("generate-lockfile") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[ADDING] too_new_child v0.0.1 (requires Rust 1.2345.0) +[ADDING] too_new_parent v0.0.1 (requires Rust 1.2345.0) + +"#]]) + .run(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] too_new_parent v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] too_new_child v0.0.1 (registry `dummy-registry`) +[DOWNLOADED] rustc_compatible v0.0.1 (registry `dummy-registry`) +[ERROR] rustc [..] is not supported by the following packages: + too_new_child@0.0.1 requires rustc 1.2345.0 + too_new_parent@0.0.1 requires rustc 1.2345.0 +Either upgrade rustc or select compatible dependency versions with +`cargo update @ --precise ` +where `` is the latest version supporting rustc [..] + + +"#]]) + .run(); + p.cargo("check --ignore-rust-version").run(); +} + +#[cargo_test] +fn resolve_with_rust_version() { + Package::new("only-newer", "1.6.0") + .rust_version("1.65.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.5.0") + .rust_version("1.55.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "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" + edition = "2015" + authors = [] + rust-version = "1.60.0" + + [dependencies] + only-newer = "1.0.0" + newer-and-older = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("generate-lockfile --ignore-rust-version") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.6.0 +└── only-newer v1.6.0 + +"#]]) + .run(); + + p.cargo("generate-lockfile") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions +[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.65.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.65.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.5.0 +└── only-newer v1.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn resolve_with_rustc() { + Package::new("only-newer", "1.6.0") + .rust_version("1.2345") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.5.0") + .rust_version("1.55.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.6.0") + .rust_version("1.2345") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + rust-version = "1.60.0" + + [dependencies] + only-newer = "1.0.0" + newer-and-older = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("generate-lockfile --ignore-rust-version") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[ADDING] newer-and-older v1.6.0 (requires Rust 1.2345) +[ADDING] only-newer v1.6.0 (requires Rust 1.2345) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.6.0 +└── only-newer v1.6.0 + +"#]]) + .run(); + + p.cargo("generate-lockfile") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions +[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.2345) +[ADDING] only-newer v1.6.0 (requires Rust 1.2345) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.5.0 +└── only-newer v1.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn resolve_with_backtracking() { + Package::new("has-rust-version", "1.6.0") + .rust_version("1.65.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("no-rust-version", "2.1.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("no-rust-version", "2.2.0") + .file("src/lib.rs", "fn other_stuff() {}") + .dep("has-rust-version", "1.6.0") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + rust-version = "1.60.0" + + [dependencies] + no-rust-version = "2" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("generate-lockfile --ignore-rust-version") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +└── no-rust-version v2.2.0 + └── has-rust-version v1.6.0 + +"#]]) + .run(); + + // Ideally we'd pick `has-rust-version` 1.6.0 which requires backtracking + p.cargo("generate-lockfile") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions +[ADDING] has-rust-version v1.6.0 (requires Rust 1.65.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +└── no-rust-version v2.2.0 + └── has-rust-version v1.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn resolve_with_multiple_rust_versions() { + Package::new(&format!("shared-only-newer"), "1.65.0") + .rust_version("1.65.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + for ver in ["1.45.0", "1.55.0", "1.65.0"] { + Package::new(&format!("shared-newer-and-older"), ver) + .rust_version(ver) + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + } + Package::new(&format!("lower-only-newer"), "1.65.0") + .rust_version("1.65.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + for ver in ["1.45.0", "1.55.0"] { + Package::new(&format!("lower-newer-and-older"), ver) + .rust_version(ver) + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + } + Package::new(&format!("higher-only-newer"), "1.65.0") + .rust_version("1.65.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + for ver in ["1.55.0", "1.65.0"] { + Package::new(&format!("higher-newer-and-older"), ver) + .rust_version(ver) + .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" + edition = "2015" + authors = [] + rust-version = "1.60.0" + + [dependencies] + higher-only-newer = "1" + higher-newer-and-older = "1" + shared-only-newer = "1" + shared-newer-and-older = "1" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "lower/Cargo.toml", + r#" + [package] + name = "lower" + version = "0.0.1" + edition = "2015" + authors = [] + rust-version = "1.50.0" + + [dependencies] + lower-only-newer = "1" + lower-newer-and-older = "1" + shared-only-newer = "1" + shared-newer-and-older = "1" + "#, + ) + .file("lower/src/main.rs", "fn main() {}") + .build(); + + p.cargo("generate-lockfile --ignore-rust-version") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 6 packages to latest compatible versions + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +higher v0.0.1 ([ROOT]/foo) +├── higher-newer-and-older v1.65.0 +├── higher-only-newer v1.65.0 +├── shared-newer-and-older v1.65.0 +└── shared-only-newer v1.65.0 + +"#]]) + .run(); + + p.cargo("generate-lockfile") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 6 packages to latest Rust 1.50.0 compatible versions +[ADDING] higher-newer-and-older v1.55.0 (available: v1.65.0, requires Rust 1.65.0) +[ADDING] higher-only-newer v1.65.0 (requires Rust 1.65.0) +[ADDING] lower-newer-and-older v1.45.0 (available: v1.55.0, requires Rust 1.55.0) +[ADDING] lower-only-newer v1.65.0 (requires Rust 1.65.0) +[ADDING] shared-newer-and-older v1.45.0 (available: v1.65.0, requires Rust 1.65.0) +[ADDING] shared-only-newer v1.65.0 (requires Rust 1.65.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +higher v0.0.1 ([ROOT]/foo) +├── higher-newer-and-older v1.55.0 +├── higher-only-newer v1.65.0 +├── shared-newer-and-older v1.45.0 +└── shared-only-newer v1.65.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn resolve_edition2024() { + Package::new("only-newer", "1.6.0") + .rust_version("1.90.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.5.0") + .rust_version("1.80.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.6.0") + .rust_version("1.90.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2024" + authors = [] + rust-version = "1.85.0" + + [dependencies] + only-newer = "1.0.0" + newer-and-older = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + // Edition2024 should resolve for MSRV + p.cargo("generate-lockfile") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest Rust 1.85.0 compatible versions +[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.90.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.90.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.5.0 +└── only-newer v1.6.0 + +"#]]) + .run(); + + // `--ignore-rust-version` has precedence over Edition2024 + p.cargo("generate-lockfile --ignore-rust-version") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[ADDING] newer-and-older v1.6.0 (requires Rust 1.90.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.90.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.6.0 +└── only-newer v1.6.0 + +"#]]) + .run(); + + // config has precedence over Edition2024 + p.cargo("generate-lockfile") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "allow") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[ADDING] newer-and-older v1.6.0 (requires Rust 1.90.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.90.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.6.0 +└── only-newer v1.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn resolve_v3() { + Package::new("only-newer", "1.6.0") + .rust_version("1.90.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.5.0") + .rust_version("1.80.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.6.0") + .rust_version("1.90.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + rust-version = "1.85.0" + resolver = "3" + + [dependencies] + only-newer = "1.0.0" + newer-and-older = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + // v3 should resolve for MSRV + p.cargo("generate-lockfile") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest Rust 1.85.0 compatible versions +[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.90.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.90.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.5.0 +└── only-newer v1.6.0 + +"#]]) + .run(); + + // `--ignore-rust-version` has precedence over v3 + p.cargo("generate-lockfile --ignore-rust-version") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[ADDING] newer-and-older v1.6.0 (requires Rust 1.90.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.90.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.6.0 +└── only-newer v1.6.0 + +"#]]) + .run(); + + // config has precedence over v3 + p.cargo("generate-lockfile") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "allow") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[ADDING] newer-and-older v1.6.0 (requires Rust 1.90.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.90.0) + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.6.0 +└── only-newer v1.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_msrv_resolve() { + 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" + edition = "2015" + authors = [] + rust-version = "1.60.0" + [dependencies] + bar = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("update") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest Rust 1.60.0 compatible version +[ADDING] bar v1.5.0 (available: v1.6.0, requires Rust 1.65.0) + +"#]]) + .run(); + p.cargo("update --ignore-rust-version") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v1.5.0 -> v1.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_precise_overrides_msrv_resolver() { + 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" + edition = "2015" + authors = [] + rust-version = "1.60.0" + [dependencies] + bar = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("update") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest Rust 1.60.0 compatible version +[ADDING] bar v1.5.0 (available: v1.6.0, requires Rust 1.65.0) + +"#]]) + .run(); + p.cargo("update --precise 1.6.0 bar") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] bar v1.5.0 -> v1.6.0 (requires Rust 1.65.0) + +"#]]) + .run(); +} + +#[cargo_test] +fn check_msrv_resolve() { + Package::new("only-newer", "1.6.0") + .rust_version("1.65.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "1.5.0") + .rust_version("1.55.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("newer-and-older", "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" + edition = "2015" + authors = [] + rust-version = "1.60.0" + + [dependencies] + only-newer = "1.0.0" + newer-and-older = "1.0.0" + "#, + ) + .file("src/main.rs", "fn main(){}") + .build(); + + p.cargo("check --ignore-rust-version") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] only-newer v1.6.0 (registry `dummy-registry`) +[DOWNLOADED] newer-and-older v1.6.0 (registry `dummy-registry`) +[CHECKING] only-newer v1.6.0 +[CHECKING] newer-and-older v1.6.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.6.0 +└── only-newer v1.6.0 + +"#]]) + .run(); + + std::fs::remove_file(p.root().join("Cargo.lock")).unwrap(); + p.cargo("check") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest Rust 1.60.0 compatible versions +[ADDING] newer-and-older v1.5.0 (available: v1.6.0, requires Rust 1.65.0) +[ADDING] only-newer v1.6.0 (requires Rust 1.65.0) +[DOWNLOADING] crates ... +[DOWNLOADED] newer-and-older v1.5.0 (registry `dummy-registry`) +[CHECKING] newer-and-older v1.5.0 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.0.1 ([ROOT]/foo) +├── newer-and-older v1.5.0 +└── only-newer v1.6.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_install_ignores_msrv_config() { + Package::new("dep", "1.0.0") + .rust_version("1.50") + .file("src/lib.rs", "fn hello() {}") + .publish(); + Package::new("dep", "1.1.0") + .rust_version("1.70") + .file("src/lib.rs", "fn hello() {}") + .publish(); + Package::new("foo", "0.0.1") + .rust_version("1.60") + .file("src/main.rs", "fn main() {}") + .dep("dep", "1") + .publish(); + + cargo_process("install foo") + .env( + "CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", + "fallback", + ) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v1.1.0 (registry `dummy-registry`) +[COMPILING] dep v1.1.0 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_install_ignores_resolver_v3_msrv_change() { + Package::new("dep", "1.0.0") + .rust_version("1.50") + .file("src/lib.rs", "fn hello() {}") + .publish(); + Package::new("dep", "1.1.0") + .rust_version("1.70") + .file("src/lib.rs", "fn hello() {}") + .publish(); + Package::new("foo", "0.0.1") + .rust_version("1.60") + .resolver("3") + .file("src/main.rs", "fn main() {}") + .dep("dep", "1") + .publish(); + + cargo_process("install foo") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`) +[INSTALLING] foo v0.0.1 +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v1.1.0 (registry `dummy-registry`) +[COMPILING] dep v1.1.0 +[COMPILING] foo v0.0.1 +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[INSTALLING] [ROOT]/home/.cargo/bin/foo[EXE] +[INSTALLED] package `foo v0.0.1` (executable `foo[EXE]`) +[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries + +"#]]) + .run(); +} + +#[cargo_test] +fn report_rust_versions() { + Package::new("dep-only-low-compatible", "1.55.0") + .rust_version("1.55.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-only-low-incompatible", "1.75.0") + .rust_version("1.75.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-only-high-compatible", "1.65.0") + .rust_version("1.65.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-only-high-incompatible", "1.75.0") + .rust_version("1.75.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-only-unset-unset", "1.0.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-only-unset-compatible", "1.75.0") + .rust_version("1.75.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-only-unset-incompatible", "1.2345.0") + .rust_version("1.2345.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-shared-compatible", "1.55.0") + .rust_version("1.55.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + Package::new("dep-shared-incompatible", "1.75.0") + .rust_version("1.75.0") + .file("src/lib.rs", "fn other_stuff() {}") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["high", "low", "unset"] + "#, + ) + .file( + "high/Cargo.toml", + r#" + [package] + name = "high" + edition = "2015" + rust-version = "1.70.0" + + [dependencies] + dep-only-high-compatible = "1" + dep-only-high-incompatible = "1" + dep-shared-compatible = "1" + dep-shared-incompatible = "1" + "#, + ) + .file("high/src/main.rs", "fn main(){}") + .file( + "low/Cargo.toml", + r#" + [package] + name = "low" + edition = "2015" + rust-version = "1.60.0" + + [dependencies] + dep-only-low-compatible = "1" + dep-only-low-incompatible = "1" + dep-shared-compatible = "1" + dep-shared-incompatible = "1" + "#, + ) + .file("low/src/main.rs", "fn main(){}") + .file( + "unset/Cargo.toml", + r#" + [package] + name = "unset" + edition = "2015" + + [dependencies] + dep-only-unset-unset = "1" + dep-only-unset-compatible = "1" + dep-only-unset-incompatible = "1" + dep-shared-compatible = "1" + dep-shared-incompatible = "1" + "#, + ) + .file("unset/src/main.rs", "fn main(){}") + .build(); + + p.cargo("update") + .env("CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS", "fallback") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 9 packages to latest Rust 1.60.0 compatible versions +[ADDING] dep-only-high-incompatible v1.75.0 (requires Rust 1.75.0) +[ADDING] dep-only-low-incompatible v1.75.0 (requires Rust 1.75.0) +[ADDING] dep-only-unset-incompatible v1.2345.0 (requires Rust 1.2345.0) +[ADDING] dep-shared-incompatible v1.75.0 (requires Rust 1.75.0) + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc.rs new file mode 100644 index 000000000..124877f54 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc.rs @@ -0,0 +1,857 @@ +//! Tests for the `cargo rustc` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_bin_manifest, basic_lib_manifest, basic_manifest, project, str}; + +#[cargo_test] +fn build_lib_for_foo() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc --lib -v").with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] [..]--out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn lib() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc --lib -v -- -C debug-assertions=off") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] [..]--out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps[..]-C debug-assertions=off[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_main_and_allow_unstable_options() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc -v --bin foo -- -C debug-assertions") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [ROOT]/foo/target/debug/deps -L dependency=[ROOT]/foo/target/debug/deps --extern foo=[ROOT]/foo/target/debug/deps/libfoo-[HASH].rlib[..]-C debug-assertions[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fails_when_trying_to_build_main_and_lib_with_args() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc -v -- -C debug-assertions") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] extra arguments to `rustc` can only be passed to one target, consider filtering +the package by passing, e.g., `--lib` or `--bin NAME` to specify a single target + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_args_to_one_of_multiple_binaries() { + let p = project() + .file("src/bin/foo.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .file("src/bin/baz.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc -v --bin bar -- -C debug-assertions") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [..]` +[RUNNING] `rustc --crate-name bar --edition=2015 src/bin/bar.rs [..]--crate-type bin --emit=[..]link[..]-C debuginfo=2 [..]-C debug-assertions[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fails_with_args_to_all_binaries() { + let p = project() + .file("src/bin/foo.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .file("src/bin/baz.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc -v -- -C debug-assertions") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] extra arguments to `rustc` can only be passed to one target, consider filtering +the package by passing, e.g., `--lib` or `--bin NAME` to specify a single target + +"#]]) + .run(); +} + +#[cargo_test] +fn fails_with_crate_type_to_multi_binaries() { + let p = project() + .file("src/bin/foo.rs", "fn main() {}") + .file("src/bin/bar.rs", "fn main() {}") + .file("src/bin/baz.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc --crate-type lib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] crate types to rustc can only be passed to one target, consider filtering +the package by passing, e.g., `--lib` or `--example` to specify a single target + +"#]]) + .run(); +} + +#[cargo_test] +fn fails_with_crate_type_to_multi_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex1" + crate-type = ["rlib"] + [[example]] + name = "ex2" + crate-type = ["rlib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex1.rs", "") + .file("examples/ex2.rs", "") + .build(); + + p.cargo("rustc -v --example ex1 --example ex2 --crate-type lib,cdylib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] crate types to rustc can only be passed to one target, consider filtering +the package by passing, e.g., `--lib` or `--example` to specify a single target + +"#]]) + .run(); +} + +#[cargo_test] +fn fails_with_crate_type_to_binary() { + let p = project().file("src/bin/foo.rs", "fn main() {}").build(); + + p.cargo("rustc --crate-type lib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] crate types can only be specified for libraries and example libraries. +Binaries, tests, and benchmarks are always the `bin` crate type + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_crate_type_for_foo() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustc -v --crate-type cdylib") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type cdylib [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_crate_type_for_foo_with_deps() { + let p = project() + .file( + "src/lib.rs", + r#" + extern crate a; + pub fn foo() { a::hello(); } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "pub fn hello() {}") + .build(); + + p.cargo("rustc -v --crate-type cdylib") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name a --edition=2015 a/src/lib.rs [..]--crate-type lib [..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type cdylib [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_crate_types_for_foo() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustc -v --crate-type lib,cdylib") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --crate-type cdylib [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_crate_type_to_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex" + crate-type = ["rlib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("rustc -v --example ex --crate-type cdylib") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]` +[RUNNING] `rustc --crate-name ex --edition=2015 examples/ex.rs [..]--crate-type cdylib [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_crate_types_to_example() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex" + crate-type = ["rlib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex.rs", "") + .build(); + + p.cargo("rustc -v --example ex --crate-type lib,cdylib") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]` +[RUNNING] `rustc --crate-name ex --edition=2015 examples/ex.rs [..]--crate-type lib --crate-type cdylib [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_crate_types_to_one_of_multi_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[example]] + name = "ex1" + crate-type = ["rlib"] + [[example]] + name = "ex2" + crate-type = ["rlib"] + "#, + ) + .file("src/lib.rs", "") + .file("examples/ex1.rs", "") + .file("examples/ex2.rs", "") + .build(); + + p.cargo("rustc -v --example ex1 --crate-type lib,cdylib") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib [..]` +[RUNNING] `rustc --crate-name ex1 --edition=2015 examples/ex1.rs [..]--crate-type lib --crate-type cdylib [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_with_args_to_one_of_multiple_tests() { + let p = project() + .file("tests/foo.rs", r#" "#) + .file("tests/bar.rs", r#" "#) + .file("tests/baz.rs", r#" "#) + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustc -v --test bar -- -C debug-assertions") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..]--crate-type lib --emit=[..]link[..]-C debuginfo=2 [..]-C metadata=[..] --out-dir [..]` +[RUNNING] `rustc --crate-name bar --edition=2015 tests/bar.rs [..]--emit=[..]link[..]-C debuginfo=2 [..]--test[..]-C debug-assertions[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_foo_with_bar_dependency() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::baz() }") + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("rustc -v -- -C debug-assertions") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.1.0 ([ROOT]/bar) +[RUNNING] `rustc --crate-name bar [..] -C debuginfo=2[..]` +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] -C debuginfo=2 [..]-C debug-assertions[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_only_bar_dependency() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::baz() }") + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("rustc -v -p bar -- -C debug-assertions") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.1.0 ([ROOT]/bar) +[RUNNING] `rustc --crate-name bar [..]--crate-type lib [..] -C debug-assertions[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn targets_selected_default() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("rustc -v") + // bin + .with_stderr_contains( + "[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin \ + --emit=[..]link[..]", + ) + // bench + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link \ + -C opt-level=3 --test [..]", + ) + // unit test + .with_stderr_does_not_contain( + "[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit=[..]link \ + -C debuginfo=2 [..]--test [..]", + ) + .run(); +} + +#[cargo_test] +fn targets_selected_all() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("rustc -v --all-targets") + // bin and unit test + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--crate-type bin --emit=[..]link[..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]--emit[..]link[..] -C debuginfo=2 [..]--test [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]].unordered() + ) + .run(); +} + +#[cargo_test] +fn fail_with_multiple_packages() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + + [dependencies.baz] + path = "../baz" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(flag = "1") { println!("Yeah from bar!"); } + } + "#, + ) + .build(); + + let _baz = project() + .at("baz") + .file("Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file( + "src/main.rs", + r#" + fn main() { + if cfg!(flag = "1") { println!("Yeah from baz!"); } + } + "#, + ) + .build(); + + foo.cargo("rustc -v -p bar -p baz") + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] the argument '--package []' cannot be used multiple times +... +"#]]) + .run(); +} + +#[cargo_test] +fn fail_with_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() { break_the_build(); }") + .build(); + + p.cargo("rustc -p '*z'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Glob patterns on package selection are not supported. + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_with_other_profile() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies] + a = { path = "a" } + "#, + ) + .file( + "src/main.rs", + r#" + #[cfg(test)] extern crate a; + + #[test] + fn foo() {} + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("rustc --profile test").run(); +} + +#[cargo_test] +fn rustc_fingerprint() { + // Verify that the fingerprint includes the rustc args. + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .build(); + + p.cargo("rustc -v -- -C debug-assertions") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]-C debug-assertions[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("rustc -v -- -C debug-assertions") + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("rustc -v") + .with_stderr_does_not_contain("-C debug-assertions") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("rustc -v") + .with_stderr_data(str![[r#" +[FRESH] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn rustc_test_with_implicit_bin() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + #[cfg(foo)] + fn f() { compile_fail!("Foo shouldn't be set."); } + fn main() {} + "#, + ) + .file( + "tests/test1.rs", + r#" + #[cfg(not(foo))] + fn f() { compile_fail!("Foo should be set."); } + "#, + ) + .build(); + + p.cargo("rustc --test test1 -v -- --cfg foo") + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name test1 --edition=2015 tests/test1.rs [..] --cfg foo[..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]` +... +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn rustc_with_print_cfg_single_target() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", r#"fn main() {} "#) + .build(); + + p.cargo("rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg") + .masquerade_as_nightly_cargo(&["print"]) + .with_stdout_data( + str![[r#" +debug_assertions +target_arch="x86_64" +target_endian="little" +target_env="msvc" +target_family="windows" +target_os="windows" +target_pointer_width="64" +target_vendor="pc" +windows +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn rustc_with_print_cfg_multiple_targets() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", r#"fn main() {} "#) + .build(); + + p.cargo("rustc -Z unstable-options --target x86_64-pc-windows-msvc --target i686-unknown-linux-gnu --print cfg") + .masquerade_as_nightly_cargo(&["print"]) + .with_stdout_data(str![[r#" +debug_assertions +target_arch="x86" +target_endian="little" +target_env="gnu" +target_family="unix" +target_os="linux" +target_pointer_width="32" +target_vendor="unknown" +unix +debug_assertions +target_arch="x86_64" +target_endian="little" +target_env="msvc" +target_family="windows" +target_os="windows" +target_pointer_width="64" +target_vendor="pc" +windows +... +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn rustc_with_print_cfg_rustflags_env_var() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", r#"fn main() {} "#) + .build(); + + p.cargo("rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg") + .masquerade_as_nightly_cargo(&["print"]) + .env("RUSTFLAGS", "-C target-feature=+crt-static") + .with_stdout_data( + str![[r#" +debug_assertions +target_arch="x86_64" +target_endian="little" +target_env="msvc" +target_family="windows" +target_feature="crt-static" +target_os="windows" +target_pointer_width="64" +target_vendor="pc" +windows +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn rustc_with_print_cfg_config_toml() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + ".cargo/config.toml", + r#" +[target.x86_64-pc-windows-msvc] +rustflags = ["-C", "target-feature=+crt-static"] +"#, + ) + .file("src/main.rs", r#"fn main() {} "#) + .build(); + + p.cargo("rustc -Z unstable-options --target x86_64-pc-windows-msvc --print cfg") + .masquerade_as_nightly_cargo(&["print"]) + .env("RUSTFLAGS", "-C target-feature=+crt-static") + .with_stdout_data( + str![[r#" +debug_assertions +target_arch="x86_64" +target_endian="little" +target_env="msvc" +target_family="windows" +target_feature="crt-static" +target_os="windows" +target_pointer_width="64" +target_vendor="pc" +windows +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn rustc_with_print_cfg_config_toml_env() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "targets/best-target.json", + r#"{ + "llvm-target": "x86_64-unknown-none", + "target-pointer-width": "64", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", + "arch": "x86_64" +}"#, + ) + .file( + ".cargo/config.toml", + r#" +[build] +target = "best-target" +[env] +RUST_TARGET_PATH = { value = "./targets", relative = true } +"#, + ) + .file("src/main.rs", r#"fn main() {} "#) + .build(); + + p.cargo("rustc -Z unstable-options --print cfg") + .masquerade_as_nightly_cargo(&["print"]) + .with_stdout_data(str!["..."].unordered()) + .run(); +} + +#[cargo_test] +fn precedence() { + // Ensure that the precedence of cargo-rustc is only lower than RUSTFLAGS, + // but higher than most flags set by cargo. + // + // See rust-lang/cargo#14346 + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2021" + + [lints.rust] + unexpected_cfgs = "allow" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("rustc --release -v -- --cfg cargo_rustc -C strip=symbols") + .env("RUSTFLAGS", "--cfg from_rustflags") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C strip=debuginfo [..]--cfg cargo_rustc -C strip=symbols --cfg from_rustflags` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc_info_cache.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc_info_cache.rs new file mode 100644 index 000000000..2ef7da92c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustc_info_cache.rs @@ -0,0 +1,188 @@ +//! Tests for the cache file for the rustc version info. + +use std::env; + +use cargo_test_support::basic_bin_manifest; +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_manifest, project}; + +const MISS: &str = "[..] rustc info cache miss[..]"; +const HIT: &str = "[..]rustc info cache hit[..]"; +const UPDATE: &str = "[..]updated rustc info cache[..]"; + +#[cargo_test] +fn rustc_info_cache() { + let p = project() + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .with_stderr_contains("[..]failed to read rustc info cache[..]") + .with_stderr_contains(MISS) + .with_stderr_does_not_contain(HIT) + .with_stderr_contains(UPDATE) + .run(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .with_stderr_contains("[..]reusing existing rustc info cache[..]") + .with_stderr_contains(HIT) + .with_stderr_does_not_contain(MISS) + .with_stderr_does_not_contain(UPDATE) + .run(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env("CARGO_CACHE_RUSTC_INFO", "0") + .with_stderr_contains("[..]rustc info cache disabled[..]") + .with_stderr_does_not_contain(UPDATE) + .run(); + + let other_rustc = { + let p = project() + .at("compiler") + .file("Cargo.toml", &basic_manifest("compiler", "0.1.0")) + .file( + "src/main.rs", + r#" + use std::process::Command; + use std::env; + + fn main() { + let mut cmd = Command::new("rustc"); + for arg in env::args_os().skip(1) { + cmd.arg(arg); + } + std::process::exit(cmd.status().unwrap().code().unwrap()); + } + "#, + ) + .build(); + p.cargo("build").run(); + + p.root() + .join("target/debug/compiler") + .with_extension(env::consts::EXE_EXTENSION) + }; + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env("RUSTC", other_rustc.display().to_string()) + .with_stderr_contains("[..]different compiler, creating new rustc info cache[..]") + .with_stderr_contains(MISS) + .with_stderr_does_not_contain(HIT) + .with_stderr_contains(UPDATE) + .run(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env("RUSTC", other_rustc.display().to_string()) + .with_stderr_contains("[..]reusing existing rustc info cache[..]") + .with_stderr_contains(HIT) + .with_stderr_does_not_contain(MISS) + .with_stderr_does_not_contain(UPDATE) + .run(); + + other_rustc.move_into_the_future(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env("RUSTC", other_rustc.display().to_string()) + .with_stderr_contains("[..]different compiler, creating new rustc info cache[..]") + .with_stderr_contains(MISS) + .with_stderr_does_not_contain(HIT) + .with_stderr_contains(UPDATE) + .run(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env("RUSTC", other_rustc.display().to_string()) + .with_stderr_contains("[..]reusing existing rustc info cache[..]") + .with_stderr_contains(HIT) + .with_stderr_does_not_contain(MISS) + .with_stderr_does_not_contain(UPDATE) + .run(); +} + +#[cargo_test] +fn rustc_info_cache_with_wrappers() { + let wrapper_project = project() + .at("wrapper") + .file("Cargo.toml", &basic_bin_manifest("wrapper")) + .file("src/main.rs", r#"fn main() { }"#) + .build(); + let wrapper = wrapper_project.bin("wrapper"); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "test" + version = "0.0.0" + authors = [] + [workspace] + "#, + ) + .file("src/main.rs", r#"fn main() { println!("hello"); }"#) + .build(); + + for &wrapper_env in ["RUSTC_WRAPPER", "RUSTC_WORKSPACE_WRAPPER"].iter() { + p.cargo("clean").with_status(0).run(); + wrapper_project.change_file( + "src/main.rs", + r#" + fn main() { + let mut args = std::env::args_os(); + let _me = args.next().unwrap(); + let rustc = args.next().unwrap(); + let status = std::process::Command::new(rustc).args(args).status().unwrap(); + std::process::exit(if status.success() { 0 } else { 1 }) + } + "#, + ); + wrapper_project.cargo("build").with_status(0).run(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env(wrapper_env, &wrapper) + .with_stderr_contains("[..]failed to read rustc info cache[..]") + .with_stderr_contains(MISS) + .with_stderr_contains(UPDATE) + .with_stderr_does_not_contain(HIT) + .with_status(0) + .run(); + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env(wrapper_env, &wrapper) + .with_stderr_contains("[..]reusing existing rustc info cache[..]") + .with_stderr_contains(HIT) + .with_stderr_does_not_contain(UPDATE) + .with_stderr_does_not_contain(MISS) + .with_status(0) + .run(); + + wrapper_project.change_file("src/main.rs", r#"fn main() { panic!() }"#); + wrapper_project.cargo("build").with_status(0).run(); + + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env(wrapper_env, &wrapper) + .with_stderr_contains("[..]different compiler, creating new rustc info cache[..]") + .with_stderr_contains(MISS) + .with_stderr_contains(UPDATE) + .with_stderr_does_not_contain(HIT) + .with_status(101) + .run(); + p.cargo("build") + .env("CARGO_LOG", "cargo::util::rustc=debug") + .env(wrapper_env, &wrapper) + .with_stderr_contains("[..]reusing existing rustc info cache[..]") + .with_stderr_contains(HIT) + .with_stderr_does_not_contain(UPDATE) + .with_stderr_does_not_contain(MISS) + .with_status(101) + .run(); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc.rs new file mode 100644 index 000000000..a502dd272 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc.rs @@ -0,0 +1,322 @@ +//! Tests for the `cargo rustdoc` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, cross_compile, project}; + +#[cargo_test] +fn rustdoc_simple() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc -v") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..] -L dependency=[ROOT]/foo/target/debug/deps [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_simple_html() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc --output-format html --open -v") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `--output-format` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/[..].html for more information about Rust release channels. +See https://github.com/rust-lang/cargo/issues/12103 for more information about the `--output-format` flag. + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "--output-format is unstable")] +fn rustdoc_simple_json() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc -Z unstable-options --output-format json -v") + .masquerade_as_nightly_cargo(&["rustdoc-output-format"]) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..] --crate-name foo [..]-o [ROOT]/foo/target/doc [..] --output-format=json[..] +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo.json + +"#]]) + .run(); + assert!(p.root().join("target/doc/foo.json").is_file()); +} + +#[cargo_test] +fn rustdoc_invalid_output_format() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc -Z unstable-options --output-format pdf -v") + .masquerade_as_nightly_cargo(&["rustdoc-output-format"]) + .with_status(1) + .with_stderr_data(str![[r#" +[ERROR] invalid value 'pdf' for '--output-format ' + [possible values: html, json] + +For more information, try '--help'. + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_json_stable() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc -Z unstable-options --output-format json -v") + .with_status(101) + .with_stderr_data( + str![[r#" +[ERROR] the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/[..].html for more information about Rust release channels. + +"#]] + ) + .run(); +} + +#[cargo_test] +fn rustdoc_json_without_unstable_options() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc --output-format json -v") + .masquerade_as_nightly_cargo(&["rustdoc-output-format"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `--output-format` flag is unstable, pass `-Z unstable-options` to enable it +See https://github.com/rust-lang/cargo/issues/12103 for more information about the `--output-format` flag. + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_args() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc -v -- --cfg=foo") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps [..]--cfg=foo[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_binary_args_passed() { + let p = project().file("src/main.rs", "").build(); + + p.cargo("rustdoc -v") + .arg("--") + .arg("--markdown-no-toc") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..] --markdown-no-toc[..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_foo_with_bar_dependency() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file("src/lib.rs", "extern crate bar; pub fn foo() {}") + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("rustdoc -v -- --cfg=foo") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[CHECKING] bar v0.0.1 ([ROOT]/bar) +[RUNNING] `rustc [..] [ROOT]/bar/src/lib.rs [..]` +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps --extern [..]--cfg=foo[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_only_bar_dependency() { + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file("src/main.rs", "extern crate bar; fn main() { bar::baz() }") + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", "pub fn baz() {}") + .build(); + + foo.cargo("rustdoc -v -p bar -- --cfg=foo") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[DOCUMENTING] bar v0.0.1 ([ROOT]/bar) +[RUNNING] `rustdoc [..] --crate-name bar [ROOT]/bar/src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps [..]--cfg=foo[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/bar/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_same_name_documents_lib() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", r#" "#) + .build(); + + p.cargo("rustdoc -v -- --cfg=foo") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..] --crate-name foo src/lib.rs -o [ROOT]/foo/target/doc [..]-C metadata=[..] -L dependency=[ROOT]/foo/target/debug/deps [..]--cfg=foo[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [features] + quux = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("rustdoc --verbose --features quux") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]feature=[..]quux[..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro_crate_type() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("rustdoc --verbose") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc --edition=2015 --crate-type proc-macro [..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn rustdoc_target() { + if cross_compile::disabled() { + return; + } + + let p = project().file("src/lib.rs", "").build(); + + p.cargo("rustdoc --verbose --target") + .arg(cross_compile::alternate()) + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustdoc [..]--crate-name foo src/lib.rs [..]--target [ALT_TARGET] -o [ROOT]/foo/target/[ALT_TARGET]/doc [..] -L dependency=[ROOT]/foo/target/[ALT_TARGET]/debug/deps -L dependency=[ROOT]/foo/target/debug/deps[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/[..]/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn fail_with_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() { break_the_build(); }") + .build(); + + p.cargo("rustdoc -p '*z'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Glob patterns on package selection are not supported. + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc_extern_html.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc_extern_html.rs new file mode 100644 index 000000000..10856fd87 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdoc_extern_html.rs @@ -0,0 +1,497 @@ +//! Tests for the -Zrustdoc-map feature. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package}; +use cargo_test_support::{paths, project, str, Project}; + +fn basic_project() -> Project { + Package::new("bar", "1.0.0") + .file("src/lib.rs", "pub struct Straw;") + .publish(); + + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + bar = "1.0" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn myfun() -> Option { + None + } + "#, + ) + .build() +} + +#[cargo_test] +fn ignores_on_stable() { + // Requires -Zrustdoc-map to use. + let p = basic_project(); + p.cargo("doc -v --no-deps") + .with_stderr_does_not_contain("[..]--extern-html-root-url[..]") + .run(); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn simple() { + // Basic test that it works with crates.io. + let p = basic_project(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://docs.rs/bar/1.0.0/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let myfun = p.read_file("target/doc/foo/fn.myfun.html"); + assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/bar/struct.Straw.html""#)); +} + +#[ignore = "Broken, temporarily disabled until https://github.com/rust-lang/rust/pull/82776 is resolved."] +#[cargo_test] +// #[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn std_docs() { + // Mapping std docs somewhere else. + // For local developers, skip this test if docs aren't installed. + let docs = std::path::Path::new(&paths::sysroot()).join("share/doc/rust/html"); + if !docs.exists() { + if cargo_util::is_ci() { + panic!("std docs are not installed, check that the rust-docs component is installed"); + } else { + eprintln!( + "documentation not found at {}, \ + skipping test (run `rustdoc component add rust-docs` to install", + docs.display() + ); + return; + } + } + let p = basic_project(); + p.change_file( + ".cargo/config.toml", + r#" + [doc.extern-map] + std = "local" + "#, + ); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_contains("[RUNNING] `rustdoc [..]--crate-name foo [..]std=file://[..]") + .run(); + let myfun = p.read_file("target/doc/foo/fn.myfun.html"); + assert!(myfun.contains(r#"share/doc/rust/html/core/option/enum.Option.html""#)); + + p.change_file( + ".cargo/config.toml", + r#" + [doc.extern-map] + std = "https://example.com/rust/" + "#, + ); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_contains( + "[RUNNING] `rustdoc [..]--crate-name foo [..]std=https://example.com/rust/[..]", + ) + .run(); + let myfun = p.read_file("target/doc/foo/fn.myfun.html"); + assert!(myfun.contains(r#"href="https://example.com/rust/core/option/enum.Option.html""#)); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn renamed_dep() { + // Handles renamed dependencies. + Package::new("bar", "1.0.0") + .file("src/lib.rs", "pub struct Straw;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + groovy = { version = "1.0", package = "bar" } + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn myfun() -> Option { + None + } + "#, + ) + .build(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://docs.rs/bar/1.0.0/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let myfun = p.read_file("target/doc/foo/fn.myfun.html"); + assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/bar/struct.Straw.html""#)); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn lib_name() { + // Handles lib name != package name. + Package::new("bar", "1.0.0") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "1.0.0" + + [lib] + name = "rumpelstiltskin" + "#, + ) + .file("src/lib.rs", "pub struct Straw;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn myfun() -> Option { + None + } + "#, + ) + .build(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]rumpelstiltskin=https://docs.rs/bar/1.0.0/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let myfun = p.read_file("target/doc/foo/fn.myfun.html"); + assert!(myfun.contains(r#"href="https://docs.rs/bar/1.0.0/rumpelstiltskin/struct.Straw.html""#)); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn alt_registry() { + // Supports other registry names. + registry::alt_init(); + Package::new("bar", "1.0.0") + .alternative(true) + .file( + "src/lib.rs", + r#" + extern crate baz; + pub struct Queen; + pub use baz::King; + "#, + ) + .registry_dep("baz", "1.0") + .publish(); + Package::new("baz", "1.0.0") + .alternative(true) + .file("src/lib.rs", "pub struct King;") + .publish(); + Package::new("grimm", "1.0.0") + .file("src/lib.rs", "pub struct Gold;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + bar = { version = "1.0", registry="alternative" } + grimm = "1.0" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn queen() -> bar::Queen { bar::Queen } + pub fn king() -> bar::King { bar::King } + pub fn gold() -> grimm::Gold { grimm::Gold } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [doc.extern-map.registries] + alternative = "https://example.com/{pkg_name}/{version}/" + crates-io = "https://docs.rs/" + "#, + ) + .build(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://example.com/bar/1.0.0/[..] --extern-html-root-url [..]baz=https://example.com/baz/1.0.0/[..] --extern-html-root-url [..]grimm=https://docs.rs/grimm/1.0.0/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let queen = p.read_file("target/doc/foo/fn.queen.html"); + assert!(queen.contains(r#"href="https://example.com/bar/1.0.0/bar/struct.Queen.html""#)); + + let king = p.read_file("target/doc/foo/fn.king.html"); + assert!(king.contains(r#"href="https://example.com/baz/1.0.0/baz/struct.King.html""#)); + + let gold = p.read_file("target/doc/foo/fn.gold.html"); + assert!(gold.contains(r#"href="https://docs.rs/grimm/1.0.0/grimm/struct.Gold.html""#)); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn multiple_versions() { + // What happens when there are multiple versions. + // NOTE: This is currently broken behavior. Rustdoc does not provide a way + // to match renamed dependencies. + Package::new("bar", "1.0.0") + .file("src/lib.rs", "pub struct Spin;") + .publish(); + Package::new("bar", "2.0.0") + .file("src/lib.rs", "pub struct Straw;") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + bar = "1.0" + bar2 = {version="2.0", package="bar"} + "#, + ) + .file( + "src/lib.rs", + " + pub fn fn1() -> bar::Spin {bar::Spin} + pub fn fn2() -> bar2::Straw {bar2::Straw} + ", + ) + .build(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://docs.rs/bar/1.0.0/[..] --extern-html-root-url [..]bar=https://docs.rs/bar/2.0.0/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let fn1 = p.read_file("target/doc/foo/fn.fn1.html"); + // This should be 1.0.0, rustdoc seems to use the last entry when there + // are duplicates. + assert!(fn1.contains(r#"href="https://docs.rs/bar/2.0.0/bar/struct.Spin.html""#)); + let fn2 = p.read_file("target/doc/foo/fn.fn2.html"); + assert!(fn2.contains(r#"href="https://docs.rs/bar/2.0.0/bar/struct.Straw.html""#)); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn rebuilds_when_changing() { + // Make sure it rebuilds if the map changes. + let p = basic_project(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--extern-html-root-url[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + + // This also tests that the map for docs.rs can be overridden. + p.change_file( + ".cargo/config.toml", + r#" + [doc.extern-map.registries] + crates-io = "https://example.com/" + "#, + ); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--extern-html-root-url [..]bar=https://example.com/bar/1.0.0/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn alt_sparse_registry() { + // Supports other registry names. + + registry::init(); + let _registry = registry::RegistryBuilder::new() + .http_index() + .alternative() + .build(); + + Package::new("bar", "1.0.0") + .alternative(true) + .file( + "src/lib.rs", + r#" + extern crate baz; + pub struct Queen; + pub use baz::King; + "#, + ) + .registry_dep("baz", "1.0") + .publish(); + Package::new("baz", "1.0.0") + .alternative(true) + .file("src/lib.rs", "pub struct King;") + .publish(); + Package::new("grimm", "1.0.0") + .file("src/lib.rs", "pub struct Gold;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + bar = { version = "1.0", registry="alternative" } + grimm = "1.0" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn queen() -> bar::Queen { bar::Queen } + pub fn king() -> bar::King { bar::King } + pub fn gold() -> grimm::Gold { grimm::Gold } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [doc.extern-map.registries] + alternative = "https://example.com/{pkg_name}/{version}/" + crates-io = "https://docs.rs/" + "#, + ) + .build(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..]--crate-name foo [..]--extern-html-root-url [..]bar=https://example.com/bar/1.0.0/[..] --extern-html-root-url [..]baz=https://example.com/baz/1.0.0/[..] --extern-html-root-url [..]grimm=https://docs.rs/grimm/1.0.0/[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + let queen = p.read_file("target/doc/foo/fn.queen.html"); + assert!(queen.contains(r#"href="https://example.com/bar/1.0.0/bar/struct.Queen.html""#)); + + let king = p.read_file("target/doc/foo/fn.king.html"); + assert!(king.contains(r#"href="https://example.com/baz/1.0.0/baz/struct.King.html""#)); + + let gold = p.read_file("target/doc/foo/fn.gold.html"); + assert!(gold.contains(r#"href="https://docs.rs/grimm/1.0.0/grimm/struct.Gold.html""#)); +} + +#[cargo_test(nightly, reason = "--extern-html-root-url is unstable")] +fn same_deps_multi_occurrence_in_dep_tree() { + // rust-lang/cargo#13543 + Package::new("baz", "1.0.0") + .file("src/lib.rs", "") + .publish(); + Package::new("bar", "1.0.0") + .file("src/lib.rs", "") + .dep("baz", "1.0") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + edition = "2018" + + [dependencies] + bar = "1.0" + baz = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [doc.extern-map.registries] + crates-io = "https://docs.rs/" + "#, + ) + .build(); + p.cargo("doc -v --no-deps -Zrustdoc-map") + .masquerade_as_nightly_cargo(&["rustdoc-map"]) + .with_stderr_does_not_contain( + "[..]--extern-html-root-url[..]bar=https://docs.rs\ + [..]--extern-html-root-url[..]baz=https://docs.rs\ + [..]--extern-html-root-url[..]baz=https://docs.rs[..]", + ) + .with_stderr_contains( + "[..]--extern-html-root-url[..]bar=https://docs.rs\ + [..]--extern-html-root-url[..]baz=https://docs.rs[..]", + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdocflags.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdocflags.rs new file mode 100644 index 000000000..c06920231 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustdocflags.rs @@ -0,0 +1,281 @@ +//! Tests for setting custom rustdoc flags. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::rustc_host; +use cargo_test_support::rustc_host_env; +use cargo_test_support::str; + +#[cargo_test] +fn parses_env() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("doc -v") + .env("RUSTDOCFLAGS", "--cfg=foo") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..] --cfg=foo[..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn parses_config() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + rustdocflags = ["--cfg", "foo"] + "#, + ) + .build(); + + p.cargo("doc -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..] --cfg foo [..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn bad_flags() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("doc") + .env("RUSTDOCFLAGS", "--bogus") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] Unrecognized option: 'bogus' +... +"#]]) + .run(); +} + +#[cargo_test] +fn rerun() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("doc").env("RUSTDOCFLAGS", "--cfg=foo").run(); + p.cargo("doc") + .env("RUSTDOCFLAGS", "--cfg=foo") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); + p.cargo("doc") + .env("RUSTDOCFLAGS", "--cfg=bar") + .with_stderr_data(str![[r#" +[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[GENERATED] [ROOT]/foo/target/doc/foo/index.html + +"#]]) + .run(); +} + +#[cargo_test] +fn rustdocflags_passed_to_rustdoc_through_cargo_test() { + let p = project() + .file( + "src/lib.rs", + r#" + //! ``` + //! assert!(cfg!(do_not_choke)); + //! ``` + "#, + ) + .build(); + + p.cargo("test --doc") + .env("RUSTDOCFLAGS", "--cfg do_not_choke") + .run(); +} + +#[cargo_test] +fn rustdocflags_passed_to_rustdoc_through_cargo_test_only_once() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("test --doc") + .env("RUSTDOCFLAGS", "--markdown-no-toc") + .run(); +} + +#[cargo_test] +fn rustdocflags_misspelled() { + let p = project().file("src/main.rs", "fn main() { }").build(); + + p.cargo("doc") + .env("RUSTDOC_FLAGS", "foo") + .with_stderr_data(str![[r#" +[WARNING] Cargo does not read `RUSTDOC_FLAGS` environment variable. Did you mean `RUSTDOCFLAGS`? +... +"#]]) + .run(); +} + +#[cargo_test] +fn whitespace() { + // Checks behavior of different whitespace characters. + let p = project().file("src/lib.rs", "").build(); + + // "too many operands" + p.cargo("doc") + .env("RUSTDOCFLAGS", "--crate-version this has spaces") + .with_stderr_data(str![[r#" +... +[ERROR] could not document `foo` +... +"#]]) + .with_status(101) + .run(); + + p.cargo("doc") + .env_remove("__CARGO_TEST_FORCE_ARGFILE") // Not applicable for argfile. + .env( + "RUSTDOCFLAGS", + "--crate-version 1111\n2222\t3333\u{00a0}4444", + ) + .run(); + + let contents = p.read_file("target/doc/foo/index.html"); + assert!(contents.contains("1111")); + assert!(contents.contains("2222")); + assert!(contents.contains("3333")); + assert!(contents.contains("4444")); +} + +#[cargo_test] +fn not_affected_by_target_rustflags() { + let cfg = if cfg!(windows) { "windows" } else { "unix" }; + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.'cfg({cfg})'] + rustflags = ["-D", "missing-docs"] + + [build] + rustdocflags = ["--cfg", "foo"] + "#, + ), + ) + .build(); + + // `cargo build` should fail due to missing docs. + p.cargo("build -v") + .with_status(101) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustc [..] -D missing-docs` +... +"#]]) + .run(); + + // `cargo doc` shouldn't fail. + p.cargo("doc -v") + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..] --cfg foo[..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn target_triple_rustdocflags_works() { + let host = rustc_host(); + let host_env = rustc_host_env(); + let p = project().file("src/lib.rs", "").build(); + + // target.triple.rustdocflags in env works + p.cargo("doc -v") + .env( + &format!("CARGO_TARGET_{host_env}_RUSTDOCFLAGS"), + "--cfg=foo", + ) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc[..]--cfg[..]foo[..]` +... +"#]]) + .run(); + + // target.triple.rustdocflags in config works + p.cargo("doc -v") + .arg("--config") + .arg(format!("target.{host}.rustdocflags=['--cfg', 'foo']")) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc [..] --cfg foo [..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn target_triple_rustdocflags_works_through_cargo_test() { + let host = rustc_host(); + let host_env = rustc_host_env(); + let p = project() + .file( + "src/lib.rs", + r#" + //! ``` + //! assert!(cfg!(foo)); + //! ``` + "#, + ) + .build(); + + // target.triple.rustdocflags in env works + p.cargo("test --doc -v") + .env( + &format!("CARGO_TARGET_{host_env}_RUSTDOCFLAGS"), + "--cfg=foo", + ) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc[..]--test[..]--cfg[..]foo[..]` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test src/lib.rs - (line 2) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + // target.triple.rustdocflags in config works + p.cargo("test --doc -v") + .arg("--config") + .arg(format!("target.{host}.rustdocflags=['--cfg', 'foo']")) + .with_stderr_data(str![[r#" +... +[RUNNING] `rustdoc[..]--test[..]--cfg[..]foo[..]` + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test src/lib.rs - (line 2) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustflags.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustflags.rs new file mode 100644 index 000000000..195d7a07f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustflags.rs @@ -0,0 +1,1792 @@ +//! Tests for setting custom rustc flags. + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{ + basic_manifest, paths, project, project_in_home, rustc_host, str, RawOutput, +}; +use snapbox::assert_data_eq; + +#[cargo_test] +fn env_rustflags_normal_source() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + "benches/d.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + "#, + ) + .build(); + + // Use RUSTFLAGS to pass an argument that will generate an error + p.cargo("check --lib") + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --bin=a") + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --example=b") + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("test") + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("bench") + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn env_rustflags_build_script() { + // RUSTFLAGS should be passed to rustc for build scripts + // when --target is not specified. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(cfg!(foo)); } + "#, + ) + .build(); + + p.cargo("check").env("RUSTFLAGS", "--cfg foo").run(); +} + +#[cargo_test] +fn env_rustflags_build_script_dep() { + // RUSTFLAGS should be passed to rustc for build scripts + // when --target is not specified. + // In this test if --cfg foo is not passed the build will fail. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + + [build-dependencies.bar] + path = "../bar" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "src/lib.rs", + r#" + fn bar() { } + #[cfg(not(foo))] + fn bar() { } + "#, + ) + .build(); + + foo.cargo("check").env("RUSTFLAGS", "--cfg foo").run(); +} + +#[cargo_test] +fn env_rustflags_normal_source_with_target() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + "benches/d.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + "#, + ) + .build(); + + let host = &rustc_host(); + + // Use RUSTFLAGS to pass an argument that will generate an error + p.cargo("check --lib --target") + .arg(host) + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --bin=a --target") + .arg(host) + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --example=b --target") + .arg(host) + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("test --target") + .arg(host) + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("bench --target") + .arg(host) + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn env_rustflags_build_script_with_target() { + // RUSTFLAGS should not be passed to rustc for build scripts + // when --target is specified. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(!cfg!(foo)); } + "#, + ) + .build(); + + let host = rustc_host(); + p.cargo("check --target") + .arg(host) + .env("RUSTFLAGS", "--cfg foo") + .run(); +} + +#[cargo_test] +fn env_rustflags_build_script_with_target_doesnt_apply_to_host_kind() { + // RUSTFLAGS should *not* be passed to rustc for build scripts when --target is specified as the + // host triple even if target-applies-to-host-kind is enabled, to match legacy Cargo behavior. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(!cfg!(foo)); } + "#, + ) + .file( + ".cargo/config.toml", + r#" + target-applies-to-host = true + "#, + ) + .build(); + + let host = rustc_host(); + p.cargo("check --target") + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg(host) + .arg("-Ztarget-applies-to-host") + .env("RUSTFLAGS", "--cfg foo") + .run(); +} + +#[cargo_test] +fn env_rustflags_build_script_dep_with_target() { + // RUSTFLAGS should not be passed to rustc for build scripts + // when --target is specified. + // In this test if --cfg foo is passed the build will fail. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + + [build-dependencies.bar] + path = "../bar" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "src/lib.rs", + r#" + fn bar() { } + #[cfg(foo)] + fn bar() { } + "#, + ) + .build(); + + let host = rustc_host(); + foo.cargo("check --target") + .arg(host) + .env("RUSTFLAGS", "--cfg foo") + .run(); +} + +#[cargo_test] +fn env_rustflags_recompile() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check").run(); + // Setting RUSTFLAGS forces a recompile + p.cargo("check") + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn env_rustflags_recompile2() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check").env("RUSTFLAGS", "--cfg foo").run(); + // Setting RUSTFLAGS forces a recompile + p.cargo("check") + .env("RUSTFLAGS", "-Z bogus") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn env_rustflags_no_recompile() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check").env("RUSTFLAGS", "--cfg foo").run(); + p.cargo("check") + .env("RUSTFLAGS", "--cfg foo") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_rustflags_normal_source() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + "benches/d.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["-Z", "bogus"] + "#, + ) + .build(); + + p.cargo("check --lib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --bin=a") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --example=b") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("bench") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn build_rustflags_build_script() { + // RUSTFLAGS should be passed to rustc for build scripts + // when --target is not specified. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(cfg!(foo)); } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["--cfg", "foo"] + "#, + ) + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn build_rustflags_build_script_dep() { + // RUSTFLAGS should be passed to rustc for build scripts + // when --target is not specified. + // In this test if --cfg foo is not passed the build will fail. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + + [build-dependencies.bar] + path = "../bar" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["--cfg", "foo"] + "#, + ) + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "src/lib.rs", + r#" + fn bar() { } + #[cfg(not(foo))] + fn bar() { } + "#, + ) + .build(); + + foo.cargo("check").run(); +} + +#[cargo_test] +fn build_rustflags_normal_source_with_target() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + "benches/d.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["-Z", "bogus"] + "#, + ) + .build(); + + let host = &rustc_host(); + + // Use build.rustflags to pass an argument that will generate an error + p.cargo("check --lib --target") + .arg(host) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --bin=a --target") + .arg(host) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --example=b --target") + .arg(host) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("test --target") + .arg(host) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("bench --target") + .arg(host) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn build_rustflags_build_script_with_target() { + // RUSTFLAGS should not be passed to rustc for build scripts + // when --target is specified. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(!cfg!(foo)); } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["--cfg", "foo"] + "#, + ) + .build(); + + let host = rustc_host(); + p.cargo("check --target").arg(host).run(); +} + +#[cargo_test] +fn build_rustflags_build_script_dep_with_target() { + // RUSTFLAGS should not be passed to rustc for build scripts + // when --target is specified. + // In this test if --cfg foo is passed the build will fail. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + build = "build.rs" + + [build-dependencies.bar] + path = "../bar" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["--cfg", "foo"] + "#, + ) + .build(); + let _bar = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "src/lib.rs", + r#" + fn bar() { } + #[cfg(foo)] + fn bar() { } + "#, + ) + .build(); + + let host = rustc_host(); + foo.cargo("check --target").arg(host).run(); +} + +#[cargo_test] +fn build_rustflags_recompile() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check").run(); + + // Setting RUSTFLAGS forces a recompile + let config = r#" + [build] + rustflags = ["-Z", "bogus"] + "#; + let config_file = paths::root().join("foo/.cargo/config.toml"); + fs::create_dir_all(config_file.parent().unwrap()).unwrap(); + fs::write(config_file, config).unwrap(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn build_rustflags_recompile2() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check").env("RUSTFLAGS", "--cfg foo").run(); + + // Setting RUSTFLAGS forces a recompile + let config = r#" + [build] + rustflags = ["-Z", "bogus"] + "#; + let config_file = paths::root().join("foo/.cargo/config.toml"); + fs::create_dir_all(config_file.parent().unwrap()).unwrap(); + fs::write(config_file, config).unwrap(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn build_rustflags_no_recompile() { + let p = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["--cfg", "foo"] + "#, + ) + .build(); + + p.cargo("check").env("RUSTFLAGS", "--cfg foo").run(); + p.cargo("check") + .env("RUSTFLAGS", "--cfg foo") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn build_rustflags_with_home_config() { + // We need a config file inside the home directory + let home = paths::home(); + let home_config = home.join(".cargo"); + fs::create_dir(&home_config).unwrap(); + fs::write( + &home_config.join("config"), + r#" + [build] + rustflags = ["-Cllvm-args=-x86-asm-syntax=intel"] + "#, + ) + .unwrap(); + + // And we need the project to be inside the home directory + // so the walking process finds the home project twice. + let p = project_in_home("foo").file("src/lib.rs", "").build(); + + p.cargo("check -v").run(); +} + +#[cargo_test] +fn target_rustflags_normal_source() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + "benches/d.rs", + r#" + #![feature(test)] + extern crate test; + #[bench] fn run1(_ben: &mut test::Bencher) { } + "#, + ) + .file( + ".cargo/config.toml", + &format!( + " + [target.{}] + rustflags = [\"-Z\", \"bogus\"] + ", + rustc_host() + ), + ) + .build(); + + p.cargo("check --lib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --bin=a") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --example=b") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("bench") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn target_rustflags_also_for_build_scripts() { + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(cfg!(foo)); } + "#, + ) + .file( + ".cargo/config.toml", + &format!( + " + [target.{}] + rustflags = [\"--cfg=foo\"] + ", + rustc_host() + ), + ) + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn target_rustflags_not_for_build_scripts_with_target() { + let host = rustc_host(); + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(!cfg!(foo)); } + "#, + ) + .file( + ".cargo/config.toml", + &format!( + " + [target.{}] + rustflags = [\"--cfg=foo\"] + ", + host + ), + ) + .build(); + + p.cargo("check --target").arg(host).run(); + + // Enabling -Ztarget-applies-to-host should not make a difference without the config setting + p.cargo("check --target") + .arg(host) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .run(); + + // Even with the setting, the rustflags from `target.` should not apply, to match the legacy + // Cargo behavior. + p.change_file( + ".cargo/config.toml", + &format!( + " + target-applies-to-host = true + + [target.{}] + rustflags = [\"--cfg=foo\"] + ", + host + ), + ); + p.cargo("check --target") + .arg(host) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .run(); +} + +#[cargo_test] +fn build_rustflags_for_build_scripts() { + let host = rustc_host(); + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + fn main() { assert!(cfg!(foo), "CFG FOO!"); } + "#, + ) + .file( + ".cargo/config.toml", + " + [build] + rustflags = [\"--cfg=foo\"] + ", + ) + .build(); + + // With "legacy" behavior, build.rustflags should apply to build scripts without --target + p.cargo("check").run(); + + // But should _not_ apply _with_ --target + p.cargo("check --target") + .arg(host) + .with_status(101) + .with_stderr_data("...\n[..]CFG FOO![..]\n...") + .run(); + + // Enabling -Ztarget-applies-to-host should not make a difference without the config setting + p.cargo("check") + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .run(); + p.cargo("check --target") + .arg(host) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .with_status(101) + .with_stderr_data("...\n[..]CFG FOO![..]\n...") + .run(); + + // When set to false though, the "proper" behavior where host artifacts _only_ pick up on + // [host] should be applied. + p.change_file( + ".cargo/config.toml", + " + target-applies-to-host = false + + [build] + rustflags = [\"--cfg=foo\"] + ", + ); + p.cargo("check") + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .with_status(101) + .with_stderr_data("...\n[..]CFG FOO![..]\n...") + .run(); + p.cargo("check --target") + .arg(host) + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .with_status(101) + .with_stderr_data("...\n[..]CFG FOO![..]\n...") + .run(); +} + +#[cargo_test] +fn host_rustflags_for_build_scripts() { + let host = rustc_host(); + let p = project() + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + // Ensure that --cfg=foo is passed. + fn main() { assert!(cfg!(foo)); } + "#, + ) + .file( + ".cargo/config.toml", + &format!( + " + target-applies-to-host = false + + [host.{}] + rustflags = [\"--cfg=foo\"] + ", + host + ), + ) + .build(); + + p.cargo("check --target") + .arg(host) + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .arg("-Ztarget-applies-to-host") + .arg("-Zhost-config") + .run(); +} + +// target.{}.rustflags takes precedence over build.rustflags +#[cargo_test] +fn target_rustflags_precedence() { + let p = project() + .file("src/lib.rs", "") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + ".cargo/config.toml", + &format!( + " + [build] + rustflags = [\"--cfg\", \"foo\"] + + [target.{}] + rustflags = [\"-Z\", \"bogus\"] + ", + rustc_host() + ), + ) + .build(); + + p.cargo("check --lib") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --bin=a") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("check --example=b") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); + p.cargo("bench") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to run `rustc` to learn about target-specific information + +Caused by: + [..]bogus[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn cfg_rustflags_normal_source() { + let p = project() + .file("src/lib.rs", "pub fn t() {}") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.'cfg({})'] + rustflags = ["--cfg", "bar"] + "#, + if rustc_host().contains("-windows-") { + "windows" + } else { + "not(windows)" + } + ), + ) + .build(); + + p.cargo("build --lib -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] --cfg bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build --bin=a -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name a [..] --cfg bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build --example=b -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name b [..] --cfg bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test --no-run -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/a-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/c-[HASH][EXE]` + +"#]]) + .run(); + + p.cargo("bench --no-run -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]` + +"#]]) + .run(); +} + +// target.'cfg(...)'.rustflags takes precedence over build.rustflags +#[cargo_test] +fn cfg_rustflags_precedence() { + let p = project() + .file("src/lib.rs", "pub fn t() {}") + .file("src/bin/a.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("tests/c.rs", "#[test] fn f() { }") + .file( + ".cargo/config.toml", + &format!( + r#" + [build] + rustflags = ["--cfg", "foo"] + + [target.'cfg({})'] + rustflags = ["--cfg", "bar"] + "#, + if rustc_host().contains("-windows-") { + "windows" + } else { + "not(windows)" + } + ), + ) + .build(); + + p.cargo("build --lib -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] --cfg bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build --bin=a -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name a [..] --cfg bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("build --example=b -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name b [..] --cfg bar` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("test --no-run -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/a-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/c-[HASH][EXE]` + +"#]]) + .run(); + + p.cargo("bench --no-run -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[RUNNING] `rustc [..] --cfg bar` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/release/deps/a-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn target_rustflags_string_and_array_form1() { + let p1 = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = ["--cfg", "foo"] + "#, + ) + .build(); + + p1.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] --cfg foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p2 = project() + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + r#" + [build] + rustflags = "--cfg foo" + "#, + ) + .build(); + + p2.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] --cfg foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn target_rustflags_string_and_array_form2() { + let p1 = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + rustflags = ["--cfg", "foo"] + "#, + rustc_host() + ), + ) + .file("src/lib.rs", "") + .build(); + + p1.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] --cfg foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + let p2 = project() + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + rustflags = "--cfg foo" + "#, + rustc_host() + ), + ) + .file("src/lib.rs", "") + .build(); + + p2.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo [..] --cfg foo` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn two_matching_in_config() { + let p1 = project() + .file( + ".cargo/config.toml", + r#" + [target.'cfg(unix)'] + rustflags = ["--cfg", 'foo="a"'] + [target.'cfg(windows)'] + rustflags = ["--cfg", 'foo="a"'] + [target.'cfg(target_pointer_width = "32")'] + rustflags = ["--cfg", 'foo="b"'] + [target.'cfg(target_pointer_width = "64")'] + rustflags = ["--cfg", 'foo="b"'] + "#, + ) + .file( + "src/main.rs", + r#" + #![allow(unexpected_cfgs)] + fn main() { + if cfg!(foo = "a") { + println!("a"); + } else if cfg!(foo = "b") { + println!("b"); + } else { + panic!() + } + } + "#, + ) + .build(); + + p1.cargo("run").run(); + p1.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn env_rustflags_misspelled() { + let p = project().file("src/main.rs", "fn main() { }").build(); + + for cmd in &["check", "build", "run", "test", "bench"] { + p.cargo(cmd) + .env("RUST_FLAGS", "foo") + .with_stderr_data( + "\ +[WARNING] Cargo does not read `RUST_FLAGS` environment variable. Did you mean `RUSTFLAGS`? +... +", + ) + .run(); + } +} + +#[cargo_test] +fn env_rustflags_misspelled_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + build = "build.rs" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() { }") + .build(); + + p.cargo("check") + .env("RUST_FLAGS", "foo") + .with_stderr_data(str![[r#" +[WARNING] Cargo does not read `RUST_FLAGS` environment variable. Did you mean `RUSTFLAGS`? +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn remap_path_prefix_works() { + // Check that remap-path-prefix works. + Package::new("bar", "0.1.0") + .file("src/lib.rs", "pub fn f() -> &'static str { file!() }") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "0.1" + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("{}", bar::f()); + } + "#, + ) + .build(); + + p.cargo("run") + .env( + "RUSTFLAGS", + format!("--remap-path-prefix={}=/foo", paths::root().display()), + ) + .with_stdout_data(str![[r#" +/foo/home/.cargo/registry/src/-[HASH]/bar-0.1.0/src/lib.rs + +"#]]) + .run(); +} + +#[cargo_test] +fn rustflags_remap_path_prefix_ignored_for_c_metadata() { + let p = project().file("src/lib.rs", "").build(); + + let build_output = p + .cargo("build -v") + .env( + "RUSTFLAGS", + "--remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo", + ) + .run(); + let first_c_metadata = dbg!(get_c_metadata(build_output)); + + p.cargo("clean").run(); + + let build_output = p + .cargo("build -v") + .env( + "RUSTFLAGS", + "--remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo", + ) + .run(); + let second_c_metadata = dbg!(get_c_metadata(build_output)); + + assert_data_eq!(first_c_metadata, second_c_metadata); +} + +#[cargo_test] +fn rustc_remap_path_prefix_ignored_for_c_metadata() { + let p = project().file("src/lib.rs", "").build(); + + let build_output = p + .cargo("rustc -v -- --remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo") + .run(); + let first_c_metadata = dbg!(get_c_metadata(build_output)); + + p.cargo("clean").run(); + + let build_output = p + .cargo("rustc -v -- --remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo") + .run(); + let second_c_metadata = dbg!(get_c_metadata(build_output)); + + assert_data_eq!(first_c_metadata, second_c_metadata); +} + +// `--remap-path-prefix` is meant to take two different binaries and make them the same but the +// rlib name, including `-Cextra-filename`, can still end up in the binary so it can't change +#[cargo_test] +fn rustflags_remap_path_prefix_ignored_for_c_extra_filename() { + let p = project().file("src/lib.rs", "").build(); + + let build_output = p + .cargo("build -v") + .env( + "RUSTFLAGS", + "--remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo", + ) + .run(); + let first_c_extra_filename = dbg!(get_c_extra_filename(build_output)); + + p.cargo("clean").run(); + + let build_output = p + .cargo("build -v") + .env( + "RUSTFLAGS", + "--remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo", + ) + .run(); + let second_c_extra_filename = dbg!(get_c_extra_filename(build_output)); + + assert_data_eq!(first_c_extra_filename, second_c_extra_filename); +} + +// `--remap-path-prefix` is meant to take two different binaries and make them the same but the +// rlib name, including `-Cextra-filename`, can still end up in the binary so it can't change +#[cargo_test] +fn rustc_remap_path_prefix_ignored_for_c_extra_filename() { + let p = project().file("src/lib.rs", "").build(); + + let build_output = p + .cargo("rustc -v -- --remap-path-prefix=/abc=/zoo --remap-path-prefix /spaced=/zoo") + .run(); + let first_c_extra_filename = dbg!(get_c_extra_filename(build_output)); + + p.cargo("clean").run(); + + let build_output = p + .cargo("rustc -v -- --remap-path-prefix=/def=/zoo --remap-path-prefix /earth=/zoo") + .run(); + let second_c_extra_filename = dbg!(get_c_extra_filename(build_output)); + + assert_data_eq!(first_c_extra_filename, second_c_extra_filename); +} + +fn get_c_metadata(output: RawOutput) -> String { + let get_c_metadata_re = + regex::Regex::new(r".* (--crate-name [^ ]+).* (-C ?metadata=[^ ]+).*").unwrap(); + + let stderr = String::from_utf8(output.stderr).unwrap(); + let mut c_metadata = get_c_metadata_re + .captures_iter(&stderr) + .map(|c| { + let (_, [name, c_metadata]) = c.extract(); + format!("{name} {c_metadata}") + }) + .collect::>(); + assert!( + !c_metadata.is_empty(), + "`{get_c_metadata_re:?}` did not match:\n```\n{stderr}\n```" + ); + c_metadata.sort(); + c_metadata.join("\n") +} + +fn get_c_extra_filename(output: RawOutput) -> String { + let get_c_extra_filename_re = + regex::Regex::new(r".* (--crate-name [^ ]+).* (-C ?extra-filename=[^ ]+).*").unwrap(); + + let stderr = String::from_utf8(output.stderr).unwrap(); + let mut c_extra_filename = get_c_extra_filename_re + .captures_iter(&stderr) + .map(|c| { + let (_, [name, c_extra_filename]) = c.extract(); + format!("{name} {c_extra_filename}") + }) + .collect::>(); + assert!( + !c_extra_filename.is_empty(), + "`{get_c_extra_filename_re:?}` did not match:\n```\n{stderr}\n```" + ); + c_extra_filename.sort(); + c_extra_filename.join("\n") +} + +#[cargo_test] +fn host_config_rustflags_with_target() { + // regression test for https://github.com/rust-lang/cargo/issues/10206 + let p = project() + .file("src/lib.rs", "") + .file("build.rs", "fn main() { assert!(cfg!(foo)); }") + .file(".cargo/config.toml", "target-applies-to-host = false") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"]) + .arg("-Zhost-config") + .arg("-Ztarget-applies-to-host") + .arg("-Zunstable-options") + .arg("--config") + .arg("host.rustflags=[\"--cfg=foo\"]") + .run(); +} + +#[cargo_test] +fn target_applies_to_host_rustflags_works() { + // Ensures that rustflags are passed to the target when + // target_applies_to_host=false + let p = project() + .file( + "src/lib.rs", + r#"#[cfg(feature = "flag")] compile_error!("flag passed");"#, + ) + .build(); + + // Use RUSTFLAGS to pass an argument that will generate an error. + p.cargo("check") + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .env("CARGO_TARGET_APPLIES_TO_HOST", "false") + .env("RUSTFLAGS", r#"--cfg feature="flag""#) + .with_status(101) + .with_stderr_data( + "[CHECKING] foo v0.0.1 ([ROOT]/foo) +[ERROR] flag passed +...", + ) + .run(); +} + +#[cargo_test] +fn target_applies_to_host_rustdocflags_works() { + // Ensures that rustflags are passed to the target when + // target_applies_to_host=false + let p = project() + .file( + "src/lib.rs", + r#"#[cfg(feature = "flag")] compile_error!("flag passed");"#, + ) + .build(); + + // Use RUSTFLAGS to pass an argument that would generate an error + // but it is ignored. + p.cargo("doc") + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .env("CARGO_TARGET_APPLIES_TO_HOST", "false") + .env("RUSTDOCFLAGS", r#"--cfg feature="flag""#) + .with_status(101) + .with_stderr_data( + "[DOCUMENTING] foo v0.0.1 ([ROOT]/foo) +[ERROR] flag passed +...", + ) + .run(); +} + +#[cargo_test] +fn host_config_shared_build_dep() { + // rust-lang/cargo#14253 + Package::new("cc", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bootstrap" + edition = "2021" + + [dependencies] + cc = "1.0.0" + + [build-dependencies] + cc = "1.0.0" + + [profile.dev] + debug = 0 + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .file( + ".cargo/config.toml", + " + target-applies-to-host=false + + [host] + rustflags = ['--cfg', 'from_host'] + + [build] + rustflags = ['--cfg', 'from_target'] + ", + ) + .build(); + + p.cargo("build -v") + .masquerade_as_nightly_cargo(&["target-applies-to-host"]) + .arg("-Ztarget-applies-to-host") + .arg("-Zhost-config") + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] cc v1.0.0 (registry `dummy-registry`) +[COMPILING] cc v1.0.0 +[RUNNING] `rustc --crate-name cc [..]--cfg from_host[..]` +[RUNNING] `rustc --crate-name cc [..]--cfg from_target[..]` +[COMPILING] bootstrap v0.0.0 ([ROOT]/foo) +[RUNNING] `rustc --crate-name build_script_build [..]--cfg from_host[..]` +[RUNNING] `[ROOT]/foo/target/debug/build/bootstrap-[HASH]/build-script-build` +[RUNNING] `rustc --crate-name bootstrap[..]--cfg from_target[..]` +[FINISHED] `dev` profile [unoptimized] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustup.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustup.rs new file mode 100644 index 000000000..c9fda4566 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/rustup.rs @@ -0,0 +1,261 @@ +//! Tests for Cargo's behavior under Rustup. + +use std::env; +use std::env::consts::EXE_EXTENSION; +use std::ffi::OsString; +use std::fs; +use std::path::{Path, PathBuf}; + +use cargo_test_support::paths::{home, root}; +use cargo_test_support::prelude::*; +use cargo_test_support::{cargo_process, process, project, str}; + +/// Helper to generate an executable. +fn make_exe(dest: &Path, name: &str, contents: &str, env: &[(&str, PathBuf)]) -> PathBuf { + let rs_name = format!("{name}.rs"); + fs::write( + root().join(&rs_name), + &format!("fn main() {{ {contents} }}"), + ) + .unwrap(); + let mut pb = process("rustc"); + env.iter().for_each(|(key, value)| { + pb.env(key, value); + }); + pb.arg("--edition=2021") + .arg(root().join(&rs_name)) + .exec() + .unwrap(); + let exe = Path::new(name).with_extension(EXE_EXTENSION); + let output = dest.join(&exe); + fs::rename(root().join(&exe), &output).unwrap(); + output +} + +fn prepend_path(path: &Path) -> OsString { + let mut paths = vec![path.to_path_buf()]; + paths.extend(env::split_paths(&env::var_os("PATH").unwrap_or_default())); + env::join_paths(paths).unwrap() +} + +struct RustupEnvironment { + /// Path for ~/.cargo/bin + cargo_bin: PathBuf, + /// Path for ~/.rustup + rustup_home: PathBuf, + /// Path to the cargo executable in the toolchain directory + /// (~/.rustup/toolchain/test-toolchain/bin/cargo.exe). + cargo_toolchain_exe: PathBuf, +} + +/// Creates an executable which prints a message and then runs the *real* rustc. +fn real_rustc_wrapper(bin_dir: &Path, message: &str) -> PathBuf { + let real_rustc = cargo_util::paths::resolve_executable("rustc".as_ref()).unwrap(); + // The toolchain rustc needs to call the real rustc. In order to do that, + // it needs to restore or clear the RUSTUP environment variables so that + // if rustup is installed, it will call the correct rustc. + let rustup_toolchain_setup = match std::env::var_os("RUSTUP_TOOLCHAIN") { + Some(t) => format!( + ".env(\"RUSTUP_TOOLCHAIN\", \"{}\")", + t.into_string().unwrap() + ), + None => format!(".env_remove(\"RUSTUP_TOOLCHAIN\")"), + }; + let mut env = vec![("CARGO_RUSTUP_TEST_real_rustc", real_rustc)]; + let rustup_home_setup = match std::env::var_os("RUSTUP_HOME") { + Some(h) => { + env.push(("CARGO_RUSTUP_TEST_RUSTUP_HOME", h.into())); + format!(".env(\"RUSTUP_HOME\", env!(\"CARGO_RUSTUP_TEST_RUSTUP_HOME\"))") + } + None => format!(".env_remove(\"RUSTUP_HOME\")"), + }; + make_exe( + bin_dir, + "rustc", + &format!( + r#" + eprintln!("{message}"); + let r = std::process::Command::new(env!("CARGO_RUSTUP_TEST_real_rustc")) + .args(std::env::args_os().skip(1)) + {rustup_toolchain_setup} + {rustup_home_setup} + .status(); + std::process::exit(r.unwrap().code().unwrap_or(2)); + "# + ), + &env, + ) +} + +/// Creates a simulation of a rustup environment with `~/.cargo/bin` and +/// `~/.rustup` directories populated with some executables that simulate +/// rustup. +fn simulated_rustup_environment() -> RustupEnvironment { + // Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo. + let rustup_home = home().join(".rustup"); + let toolchain_bin = rustup_home + .join("toolchains") + .join("test-toolchain") + .join("bin"); + toolchain_bin.mkdir_p(); + let rustc_toolchain_exe = real_rustc_wrapper(&toolchain_bin, "real rustc running"); + let cargo_toolchain_exe = make_exe( + &toolchain_bin, + "cargo", + r#"panic!("cargo toolchain should not be called");"#, + &[], + ); + + // Set up ~/.cargo/bin with a typical set of rustup proxies. + let cargo_bin = home().join(".cargo").join("bin"); + cargo_bin.mkdir_p(); + + let rustc_proxy = make_exe( + &cargo_bin, + "rustc", + &format!( + r#" + match std::env::args().next().unwrap().as_ref() {{ + "rustc" => {{}} + arg => panic!("proxy only supports rustc, got {{arg:?}}"), + }} + eprintln!("rustc proxy running"); + let r = std::process::Command::new(env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe")) + .args(std::env::args_os().skip(1)) + .status(); + std::process::exit(r.unwrap().code().unwrap_or(2)); + "# + ), + &[("CARGO_RUSTUP_TEST_rustc_toolchain_exe", rustc_toolchain_exe)], + ); + fs::hard_link( + &rustc_proxy, + cargo_bin.join("cargo").with_extension(EXE_EXTENSION), + ) + .unwrap(); + fs::hard_link( + &rustc_proxy, + cargo_bin.join("rustup").with_extension(EXE_EXTENSION), + ) + .unwrap(); + + RustupEnvironment { + cargo_bin, + rustup_home, + cargo_toolchain_exe, + } +} + +#[cargo_test] +fn typical_rustup() { + // Test behavior under a typical rustup setup with a normal toolchain. + let RustupEnvironment { + cargo_bin, + rustup_home, + cargo_toolchain_exe, + } = simulated_rustup_environment(); + + // Set up a project and run a normal cargo build. + let p = project().file("src/lib.rs", "").build(); + // The path is modified so that cargo will call `rustc` from + // `~/.cargo/bin/rustc to use our custom rustup proxies. + let path = prepend_path(&cargo_bin); + p.cargo("check") + .env("RUSTUP_TOOLCHAIN", "test-toolchain") + .env("RUSTUP_HOME", &rustup_home) + .env("PATH", &path) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +real rustc running +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Do a similar test, but with a toolchain link that does not have cargo + // (which normally would do a fallback to nightly/beta/stable). + cargo_toolchain_exe.rm_rf(); + p.build_dir().rm_rf(); + + p.cargo("check") + .env("RUSTUP_TOOLCHAIN", "test-toolchain") + .env("RUSTUP_HOME", &rustup_home) + .env("PATH", &path) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +real rustc running +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +// This doesn't work on Windows because Cargo forces the PATH to contain the +// sysroot_libdir, which is actually `bin`, preventing the test from +// overriding the bin directory. +#[cargo_test(ignore_windows = "PATH can't be overridden on Windows")] +fn custom_calls_other_cargo() { + // Test behavior when a custom subcommand tries to manipulate PATH to use + // a different toolchain. + let RustupEnvironment { + cargo_bin, + rustup_home, + cargo_toolchain_exe: _, + } = simulated_rustup_environment(); + + // Create a directory with a custom toolchain (outside of the rustup universe). + let custom_bin = root().join("custom-bin"); + custom_bin.mkdir_p(); + // `cargo` points to the real cargo. + let cargo_exe = cargo_test_support::cargo_exe(); + fs::hard_link(&cargo_exe, custom_bin.join(cargo_exe.file_name().unwrap())).unwrap(); + // `rustc` executes the real rustc. + real_rustc_wrapper(&custom_bin, "custom toolchain rustc running"); + + // A project that cargo-custom will try to build. + let p = project().file("src/lib.rs", "").build(); + + // Create a custom cargo subcommand. + // This will modify PATH to a custom toolchain and call cargo from that. + make_exe( + &cargo_bin, + "cargo-custom", + r#" + use std::env; + use std::process::Command; + + eprintln!("custom command running"); + + let mut paths = vec![std::path::PathBuf::from(env!("CARGO_RUSTUP_TEST_custom_bin"))]; + paths.extend(env::split_paths(&env::var_os("PATH").unwrap_or_default())); + let path = env::join_paths(paths).unwrap(); + + let status = Command::new("cargo") + .arg("check") + .current_dir(env!("CARGO_RUSTUP_TEST_project_dir")) + .env("PATH", path) + .status() + .unwrap(); + assert!(status.success()); + "#, + &[ + ("CARGO_RUSTUP_TEST_custom_bin", custom_bin), + ("CARGO_RUSTUP_TEST_project_dir", p.root()), + ], + ); + + cargo_process("custom") + // Set these to simulate what would happen when running under rustup. + // We want to make sure that cargo-custom does not try to use the + // rustup proxies. + .env("RUSTUP_TOOLCHAIN", "test-toolchain") + .env("RUSTUP_HOME", &rustup_home) + .with_stderr_data(str![[r#" +custom command running +[CHECKING] foo v0.0.1 ([ROOT]/foo) +custom toolchain rustc running +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/script.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/script.rs new file mode 100644 index 000000000..20fa7bcb3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/script.rs @@ -0,0 +1,1888 @@ +use std::fs; + +use cargo_test_support::basic_manifest; +use cargo_test_support::paths::cargo_home; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +const ECHO_SCRIPT: &str = r#"#!/usr/bin/env cargo + +fn main() { + let mut args = std::env::args_os(); + let bin = args.next().unwrap().to_str().unwrap().to_owned(); + let args = args.collect::>(); + println!("bin: {bin}"); + println!("args: {args:?}"); +} + +#[test] +fn test () {} +"#; + +#[cfg(unix)] +fn path() -> Vec { + std::env::split_paths(&std::env::var_os("PATH").unwrap_or_default()).collect() +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn basic_rs() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript -v echo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] echo v0.0.0 ([ROOT]/foo/echo.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn basic_path() { + let p = cargo_test_support::project() + .file("echo", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript -v ./echo") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] echo v0.0.0 ([ROOT]/foo/echo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn path_required() { + let p = cargo_test_support::project() + .file("echo", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript -v echo") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] no such command: `echo` + +[HELP] a command with a similar name exists: `bench` + +[HELP] view all installed commands with `cargo --list` +[HELP] find a package to install `echo` with `cargo search cargo-echo` +[HELP] To run the file `echo`, provide a relative path like `./echo` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +#[cfg(unix)] +fn manifest_precedence_over_plugins() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .executable(std::path::Path::new("path-test").join("cargo-echo.rs"), "") + .build(); + + // With path - fmt is there with known description + let mut path = path(); + path.push(p.root().join("path-test")); + let path = std::env::join_paths(path.iter()).unwrap(); + + p.cargo("-Zscript -v echo.rs") + .env("PATH", &path) + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] echo v0.0.0 ([ROOT]/foo/echo.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/echo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +#[cfg(unix)] +fn warn_when_plugin_masks_manifest_on_stable() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .executable(std::path::Path::new("path-test").join("cargo-echo.rs"), "") + .build(); + + let mut path = path(); + path.push(p.root().join("path-test")); + let path = std::env::join_paths(path.iter()).unwrap(); + + p.cargo("-v echo.rs") + .env("PATH", &path) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[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 . + +"#]]) + .run(); +} + +#[cargo_test] +fn requires_nightly() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-v echo.rs") + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] running the file `echo.rs` requires `-Zscript` + +"#]]) + .run(); +} + +#[cargo_test] +fn requires_z_flag() { + let p = cargo_test_support::project() + .file("echo.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-v echo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] running the file `echo.rs` requires `-Zscript` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn clean_output_with_edition() { + let script = r#"#!/usr/bin/env cargo +--- +[package] +edition = "2018" +--- + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +Hello world! + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn warning_without_edition() { + let script = r#"#!/usr/bin/env cargo +--- +[package] +--- + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +Hello world! + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn rebuild() { + let script = r#"#!/usr/bin/env cargo-eval + +fn main() { + let msg = option_env!("_MESSAGE").unwrap_or("undefined"); + println!("msg = {}", msg); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +msg = undefined + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); + + // Verify we don't rebuild + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +msg = undefined + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); + + // Verify we do rebuild + p.cargo("-Zscript -v script.rs") + .env("_MESSAGE", "hello") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +msg = hello + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn use_cargo_home_config() { + let script = ECHO_SCRIPT; + let _ = cargo_test_support::project() + .at("script") + .file("script.rs", script) + .build(); + + let p = cargo_test_support::project() + .file( + ".cargo/config.toml", + r#" +[build] +rustc = "non-existent-rustc" +"#, + ) + .file("script.rs", script) + .build(); + + // Verify that the config from the current directory is used + p.cargo("-Zscript script.rs -NotAnArg") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: ["-NotAnArg"] + +"#]]) + .run(); + + // Verify that the config from the parent directory is not used + p.cargo("-Zscript ../script/script.rs -NotAnArg") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: ["-NotAnArg"] + +"#]]) + .run(); + + // Write a global config.toml in the cargo home directory + let cargo_home = cargo_home(); + fs::write( + &cargo_home.join("config.toml"), + r#" +[build] +rustc = "non-existent-rustc" +"#, + ) + .unwrap(); + + // Verify the global config is used + p.cargo("-Zscript script.rs -NotAnArg") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] could not execute process `non-existent-rustc -vV` (never executed) + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn default_programmatic_verbosity() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript script.rs -NotAnArg") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: ["-NotAnArg"] + +"#]]) + .with_stderr_data("") + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn quiet() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -q script.rs -NotAnArg") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: ["-NotAnArg"] + +"#]]) + .with_stderr_data("") + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_line_numbering_preserved() { + let script = r#"#!/usr/bin/env cargo + +fn main() { + println!("line: {}", line!()); +} +"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +line: 4 + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_escaped_hyphen_arg() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v -- script.rs -NotAnArg") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: ["-NotAnArg"] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] -NotAnArg` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_unescaped_hyphen_arg() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs -NotAnArg") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: ["-NotAnArg"] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] -NotAnArg` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_same_flags() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs --help") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: ["--help"] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] --help` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_name_has_weird_chars() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("s-h.w§c!.rs", script) + .build(); + + p.cargo("-Zscript -v s-h.w§c!.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/s-h-w-c-[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] s-h-w-c- v0.0.0 ([ROOT]/foo/s-h.w§c!.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/s-h-w-c-[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_name_has_leading_number() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("42answer.rs", script) + .build(); + + p.cargo("-Zscript -v 42answer.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/answer[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] answer v0.0.0 ([ROOT]/foo/42answer.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/answer[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_name_is_number() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project().file("42.rs", script).build(); + + p.cargo("-Zscript -v 42.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/package[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] package v0.0.0 ([ROOT]/foo/42.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/package[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn script_like_dir() { + let p = cargo_test_support::project() + .file("foo.rs/foo", "something") + .build(); + + p.cargo("-Zscript -v foo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such file or subcommand `foo.rs`: `foo.rs` is a directory + +"#]]) + .run(); +} + +#[cargo_test] +fn non_existent_rs() { + let p = cargo_test_support::project().build(); + + p.cargo("-Zscript -v foo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no such file or subcommand `foo.rs` + +"#]]) + .run(); +} + +#[cargo_test] +fn non_existent_rs_stable() { + let p = cargo_test_support::project().build(); + + p.cargo("-v foo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] no such subcommand `foo.rs` + +"#]]) + .run(); +} + +#[cargo_test] +fn did_you_mean_file() { + let p = cargo_test_support::project() + .file("food.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript -v foo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] no such file or subcommand `foo.rs` +[HELP] there is a script with a similar name: `./food.rs` + +"#]]) + .run(); +} + +#[cargo_test] +fn did_you_mean_file_stable() { + let p = cargo_test_support::project() + .file("food.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-v foo.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] no such subcommand `foo.rs` +[HELP] there is a script with a similar name: `./food.rs` (requires `-Zscript`) + +"#]]) + .run(); +} + +#[cargo_test] +fn did_you_mean_command() { + let p = cargo_test_support::project().build(); + + p.cargo("-Zscript -v build--manifest-path=./Cargo.toml") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] no such file or subcommand `build--manifest-path=./Cargo.toml` +[HELP] there is a command with a similar name: `build --manifest-path=./Cargo.toml` + +"#]]) + .run(); +} + +#[cargo_test] +fn did_you_mean_command_stable() { + let p = cargo_test_support::project().build(); + + p.cargo("-v build--manifest-path=./Cargo.toml") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] no such subcommand `build--manifest-path=./Cargo.toml` +[HELP] there is a command with a similar name: `build --manifest-path=./Cargo.toml` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_name_same_as_dependency() { + Package::new("script", "1.0.0").publish(); + let script = r#"#!/usr/bin/env cargo +--- +[dependencies] +script = "1.0.0" +--- + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs --help") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +Hello world! + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest Rust [..] compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] script v1.0.0 (registry `dummy-registry`) +[COMPILING] script v1.0.0 +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] --help` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_path_dep() { + let script = r#"#!/usr/bin/env cargo +--- +[dependencies] +bar.path = "./bar" +--- + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .file("src/lib.rs", "pub fn foo() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("-Zscript -v script.rs --help") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +Hello world! + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[LOCKING] 1 package to latest Rust [..] compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] --help` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_no_build_rs() { + let script = r#"#!/usr/bin/env cargo + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .file("build.rs", "broken") + .build(); + + p.cargo("-Zscript -v script.rs --help") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +Hello world! + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] --help` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_no_autobins() { + let script = r#"#!/usr/bin/env cargo + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .file("src/bin/not-script/main.rs", "fn main() {}") + .build(); + + p.cargo("-Zscript -v script.rs --help") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +Hello world! + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] --help` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn test_no_autolib() { + let script = r#"#!/usr/bin/env cargo + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .file("src/lib.rs", r#"compile_error!{"must not be built"}"#) + .build(); + + p.cargo("-Zscript -v script.rs --help") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +Hello world! + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] --help` + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_workspace() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +package.edition = "2021" + +[workspace] +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `workspace` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_lib() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +package.edition = "2021" + +[lib] +name = "script" +path = "script.rs" +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `lib` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_bin() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +package.edition = "2021" + +[[bin]] +name = "script" +path = "script.rs" +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `bin` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_example() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +package.edition = "2021" + +[[example]] +name = "script" +path = "script.rs" +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `example` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_test() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +package.edition = "2021" + +[[test]] +name = "script" +path = "script.rs" +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `test` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_bench() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +package.edition = "2021" + +[[bench]] +name = "script" +path = "script.rs" +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `bench` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_package_build() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +[package] +edition = "2021" +build = "script.rs" +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `package.build` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_package_links() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +[package] +edition = "2021" +links = "script" +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `package.links` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_package_autolib() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +[package] +edition = "2021" +autolib = true +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `package.autolib` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_package_autobins() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +[package] +edition = "2021" +autobins = true +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `package.autobins` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_package_autoexamples() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +[package] +edition = "2021" +autoexamples = true +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `package.autoexamples` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_package_autotests() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +[package] +edition = "2021" +autotests = true +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `package.autotests` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test] +fn disallow_explicit_package_autobenches() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#" +---- +[package] +edition = "2021" +autobenches = true +---- + +fn main() {} +"#, + ) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/script.rs` + +Caused by: + `package.autobenches` is not allowed in embedded manifests + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn implicit_target_dir() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn no_local_lockfile() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + let local_lockfile_path = p.root().join("Cargo.lock"); + + assert!(!local_lockfile_path.exists()); + + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); + + assert!(!local_lockfile_path.exists()); +} + +#[cargo_test] +fn cmd_check_requires_nightly() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("check --manifest-path script.rs") + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] embedded manifest `[ROOT]/foo/script.rs` requires `-Zscript` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_check_requires_z_flag() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("check --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] embedded manifest `[ROOT]/foo/script.rs` requires `-Zscript` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn cmd_check_with_embedded() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript check --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[CHECKING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_check_with_missing_script_rs() { + let p = cargo_test_support::project().build(); + + p.cargo("-Zscript check --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] the manifest-path must be a path to a Cargo.toml file + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_check_with_missing_script() { + let p = cargo_test_support::project().build(); + + p.cargo("-Zscript check --manifest-path script") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[ERROR] the manifest-path must be a path to a Cargo.toml file + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn cmd_build_with_embedded() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript build --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn cmd_test_with_embedded() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript test --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" + +running 1 test +test test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests script.rs ([ROOT]/home/.cargo/target/[HASH]/debug/deps/script-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn cmd_clean_with_embedded() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + // Ensure there is something to clean + p.cargo("-Zscript script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .run(); + + p.cargo("-Zscript clean --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[REMOVED] [FILE_NUM] files, [FILE_SIZE]B total + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_generate_lockfile_with_embedded() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript generate-lockfile --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_metadata_with_embedded() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript metadata --manifest-path script.rs --format-version=1") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2024", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/script.rs#script@0.0.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/script.rs", + "metadata": null, + "name": "script", + "publish": [], + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2024", + "kind": [ + "bin" + ], + "name": "script", + "src_path": "[ROOT]/foo/script.rs", + "test": true + } + ], + "version": "0.0.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [], + "deps": [], + "features": [], + "id": "path+[ROOTURL]/foo/script.rs#script@0.0.0" + } + ], + "root": "path+[ROOTURL]/foo/script.rs#script@0.0.0" + }, + "target_directory": "[ROOT]/home/.cargo/target/[HASH]", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo/script.rs#script@0.0.0" + ], + "workspace_members": [ + "path+[ROOTURL]/foo/script.rs#script@0.0.0" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_read_manifest_with_embedded() { + let script = ECHO_SCRIPT; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript read-manifest --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data( + str![[r#" +{ + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2024", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo/script.rs#script@0.0.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/script.rs", + "metadata": null, + "name": "script", + "publish": [], + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "bin" + ], + "doc": true, + "doctest": false, + "edition": "2024", + "kind": [ + "bin" + ], + "name": "script", + "src_path": "[ROOT]/foo/script.rs", + "test": true + } + ], + "version": "0.0.0" +} +"#]] + .is_json(), + ) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn cmd_run_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript run --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +bin: [ROOT]/home/.cargo/target/[HASH]/debug/script[EXE] +args: [] + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_tree_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript tree --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +script v0.0.0 ([ROOT]/foo/script.rs) + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_update_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript update --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data("") + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_verify_project_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript verify-project --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data( + str![[r#" +{ + "success": "true" +} +"#]] + .is_json(), + ) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn cmd_pkgid_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .run(); + + p.cargo("-Zscript pkgid --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +path+[ROOTURL]/foo/script.rs#script@0.0.0 + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_pkgid_with_embedded_no_lock_file() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript pkgid --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[ERROR] a Cargo.lock must exist for this command + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn cmd_pkgid_with_embedded_dep() { + Package::new("dep", "1.0.0").publish(); + let script = r#"#!/usr/bin/env cargo +--- +[dependencies] +dep = "1.0.0" +--- + +fn main() { + println!("Hello world!"); +}"#; + let p = cargo_test_support::project() + .file("script.rs", script) + .build(); + + p.cargo("-Zscript script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .run(); + + p.cargo("-Zscript pkgid --manifest-path script.rs -p dep") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +registry+https://github.com/rust-lang/crates.io-index#dep@1.0.0 + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn script_as_dep() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "Cargo.toml", + r#" +[package] +name = "foo" +version = "0.1.0" + +[dependencies] +script.path = "script.rs" +"#, + ) + .build(); + + p.cargo("build") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] no edition set: defaulting to the 2015 edition while the latest is 2024 +[ERROR] failed to get `script` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `script` + +Caused by: + Unable to update [ROOT]/foo/script.rs + +Caused by: + Single file packages cannot be used as dependencies + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_install_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript install --path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `[ROOT]/foo/script.rs` is not a directory. --path must point to a directory containing a Cargo.toml file. + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_package_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript package --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[ERROR] [ROOT]/foo/script.rs is unsupported by `cargo package` + +"#]]) + .run(); +} + +#[cargo_test] +fn cmd_publish_with_embedded() { + let p = cargo_test_support::project() + .file("script.rs", ECHO_SCRIPT) + .build(); + + p.cargo("-Zscript publish --manifest-path script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[ERROR] [ROOT]/foo/script.rs is unsupported by `cargo publish` + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "edition2024 hasn't hit stable yet")] +fn manifest_path_env() { + let p = cargo_test_support::project() + .file( + "script.rs", + r#"#!/usr/bin/env cargo + +fn main() { + let path = env!("CARGO_MANIFEST_PATH"); + println!("CARGO_MANIFEST_PATH: {}", path); +} +"#, + ) + .build(); + p.cargo("-Zscript -v script.rs") + .masquerade_as_nightly_cargo(&["script"]) + .with_stdout_data(str![[r#" +CARGO_MANIFEST_PATH: [ROOT]/foo/script.rs + +"#]]) + .with_stderr_data(str![[r#" +[WARNING] `package.edition` is unspecified, defaulting to `2024` +[COMPILING] script v0.0.0 ([ROOT]/foo/script.rs) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/home/.cargo/target/[HASH]/debug/script[EXE]` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/search.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/search.rs new file mode 100644 index 000000000..872036067 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/search.rs @@ -0,0 +1,226 @@ +//! Tests for the `cargo search` command. + +use std::collections::HashSet; + +use cargo::util::cache_lock::CacheLockMode; +use cargo_test_support::cargo_process; +use cargo_test_support::paths; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{RegistryBuilder, Response}; +use cargo_test_support::str; + +const SEARCH_API_RESPONSE: &[u8] = br#" +{ + "crates": [{ + "created_at": "2014-11-16T20:17:35Z", + "description": "Design by contract style assertions for Rust", + "documentation": null, + "downloads": 2, + "homepage": null, + "id": "hoare", + "keywords": [], + "license": null, + "links": { + "owners": "/api/v1/crates/hoare/owners", + "reverse_dependencies": "/api/v1/crates/hoare/reverse_dependencies", + "version_downloads": "/api/v1/crates/hoare/downloads", + "versions": "/api/v1/crates/hoare/versions" + }, + "max_version": "0.1.1", + "name": "hoare", + "repository": "https://github.com/nick29581/libhoare", + "updated_at": "2014-11-20T21:49:21Z", + "versions": null + }, + { + "id": "postgres", + "name": "postgres", + "updated_at": "2020-05-01T23:17:54.335921+00:00", + "versions": null, + "keywords": null, + "categories": null, + "badges": [ + { + "badge_type": "circle-ci", + "attributes": { + "repository": "sfackler/rust-postgres", + "branch": null + } + } + ], + "created_at": "2014-11-24T02:34:44.756689+00:00", + "downloads": 535491, + "recent_downloads": 88321, + "max_version": "0.17.3", + "newest_version": "0.17.3", + "description": "A native, synchronous PostgreSQL client", + "homepage": null, + "documentation": null, + "repository": "https://github.com/sfackler/rust-postgres", + "links": { + "version_downloads": "/api/v1/crates/postgres/downloads", + "versions": "/api/v1/crates/postgres/versions", + "owners": "/api/v1/crates/postgres/owners", + "owner_team": "/api/v1/crates/postgres/owner_team", + "owner_user": "/api/v1/crates/postgres/owner_user", + "reverse_dependencies": "/api/v1/crates/postgres/reverse_dependencies" + }, + "exact_match": true + } + ], + "meta": { + "total": 2 + } +}"#; + +const SEARCH_RESULTS: &str = "\ +hoare = \"0.1.1\" # Design by contract style assertions for Rust +postgres = \"0.17.3\" # A native, synchronous PostgreSQL client +"; + +#[must_use] +fn setup() -> RegistryBuilder { + RegistryBuilder::new() + .http_api() + .add_responder("/api/v1/crates", |_, _| Response { + code: 200, + headers: vec![], + body: SEARCH_API_RESPONSE.to_vec(), + }) +} + +#[cargo_test] +fn not_update() { + let registry = setup().build(); + + use cargo::core::{Shell, SourceId}; + use cargo::sources::source::Source; + use cargo::sources::RegistrySource; + use cargo::util::GlobalContext; + + let sid = SourceId::for_registry(registry.index_url()).unwrap(); + let gctx = GlobalContext::new( + Shell::from_write(Box::new(Vec::new())), + paths::root(), + paths::home().join(".cargo"), + ); + let lock = gctx + .acquire_package_cache_lock(CacheLockMode::DownloadExclusive) + .unwrap(); + let mut regsrc = RegistrySource::remote(sid, &HashSet::new(), &gctx).unwrap(); + regsrc.invalidate_cache(); + regsrc.block_until_ready().unwrap(); + drop(lock); + + cargo_process("search postgres") + .replace_crates_io(registry.index_url()) + .with_stdout_data(SEARCH_RESULTS) + // without "Updating ... index" + .with_stderr_data(str![[r#" +[NOTE] to learn more about a package, run `cargo info ` + +"#]]) + .run(); +} + +#[cargo_test] +fn replace_default() { + let registry = setup().build(); + + cargo_process("search postgres") + .replace_crates_io(registry.index_url()) + .with_stdout_data(SEARCH_RESULTS) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[NOTE] to learn more about a package, run `cargo info ` + +"#]]) + .run(); +} + +#[cargo_test] +fn simple() { + let registry = setup().build(); + + cargo_process("search postgres --index") + .arg(registry.index_url().as_str()) + .with_stdout_data(SEARCH_RESULTS) + .with_stderr_data(str![[r#" +[UPDATING] `[ROOT]/registry` index +[NOTE] to learn more about a package, run `cargo info ` + +"#]]) + .run(); +} + +#[cargo_test] +fn multiple_query_params() { + let registry = setup().build(); + + cargo_process("search postgres sql --index") + .arg(registry.index_url().as_str()) + .with_stdout_data(SEARCH_RESULTS) + .with_stderr_data(str![[r#" +[UPDATING] `[ROOT]/registry` index +[NOTE] to learn more about a package, run `cargo info ` + +"#]]) + .run(); +} + +#[cargo_test] +fn ignore_quiet() { + let registry = setup().build(); + + cargo_process("search -q postgres") + .replace_crates_io(registry.index_url()) + .with_stdout_data(SEARCH_RESULTS) + .run(); +} + +#[cargo_test] +fn colored_results() { + let registry = setup().build(); + + cargo_process("search --color=never postgres") + .replace_crates_io(registry.index_url()) + .with_stdout_does_not_contain("[..]\x1b[[..]") + .run(); + + cargo_process("search --color=always postgres") + .replace_crates_io(registry.index_url()) + .with_stdout_data( + "\ +... +[..]\x1b[[..] +... +", + ) + .run(); +} + +#[cargo_test] +fn auth_required_failure() { + let server = setup().auth_required().no_configure_token().build(); + + cargo_process("search postgres") + .replace_crates_io(server.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[ERROR] no token found, please run `cargo login` +or use environment variable CARGO_REGISTRY_TOKEN + +"#]]) + .run(); +} + +#[cargo_test] +fn auth_required() { + let server = setup().auth_required().build(); + + cargo_process("search postgres") + .replace_crates_io(server.index_url()) + .with_stdout_data(SEARCH_RESULTS) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/shell_quoting.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/shell_quoting.rs new file mode 100644 index 000000000..d5d6800d5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/shell_quoting.rs @@ -0,0 +1,43 @@ +//! This file tests that when the commands being run are shown +//! in the output, their arguments are quoted properly +//! so that the command can be run in a terminal. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::str; + +#[cargo_test] +fn features_are_quoted() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = ["mikeyhew@example.com"] + edition = "2015" + + [features] + some_feature = [] + default = ["some_feature"] + "#, + ) + .file("src/main.rs", "fn main() {error}") + .build(); + + p.cargo("check -v") + .env("MSYSTEM", "1") + .with_status(101) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] --cfg 'feature="default"' --cfg 'feature="some_feature"' [..]` +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +Caused by: + process didn't exit successfully: [..] --cfg 'feature="default"' --cfg 'feature="some_feature"' [..] + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/source_replacement.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/source_replacement.rs new file mode 100644 index 000000000..a61314056 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/source_replacement.rs @@ -0,0 +1,339 @@ +//! Tests for `[source]` table (source replacement). + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Package, RegistryBuilder, TestRegistry}; +use cargo_test_support::{cargo_process, paths, project, str, t}; + +fn setup_replacement(config: &str) -> TestRegistry { + let crates_io = RegistryBuilder::new() + .no_configure_registry() + .http_api() + .build(); + + let root = paths::root(); + t!(fs::create_dir(&root.join(".cargo"))); + t!(fs::write(root.join(".cargo/config.toml"), config,)); + crates_io +} + +#[cargo_test] +fn crates_io_token_not_sent_to_replacement() { + // verifies that the crates.io token is not sent to a replacement registry during publish. + let crates_io = setup_replacement( + r#" + [source.crates-io] + replace-with = 'alternative' + "#, + ); + let _alternative = RegistryBuilder::new() + .alternative() + .http_api() + .no_configure_token() + .build(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish --no-verify --registry crates-io") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +... +"#]]) + .run(); +} + +#[cargo_test] +fn token_sent_to_correct_registry() { + // verifies that the crates.io token is not sent to a replacement registry during yank. + let crates_io = setup_replacement( + r#" + [source.crates-io] + replace-with = 'alternative' + "#, + ); + let _alternative = RegistryBuilder::new().alternative().http_api().build(); + + cargo_process("yank foo@0.0.1 --registry crates-io") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[YANK] foo@0.0.1 + +"#]]) + .run(); + + cargo_process("yank foo@0.0.1 --registry alternative") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[YANK] foo@0.0.1 + +"#]]) + .run(); +} + +#[cargo_test] +fn ambiguous_registry() { + // verifies that an error is issued when a source-replacement is configured + // and no --registry argument is given. + let crates_io = setup_replacement( + r#" + [source.crates-io] + replace-with = 'alternative' + "#, + ); + let _alternative = RegistryBuilder::new() + .alternative() + .http_api() + .no_configure_token() + .build(); + + cargo_process("yank foo@0.0.1") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] crates-io is replaced with remote registry alternative; +include `--registry alternative` or `--registry crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn yank_with_default_crates_io() { + // verifies that no error is given when registry.default is used. + let crates_io = setup_replacement( + r#" + [source.crates-io] + replace-with = 'alternative' + + [registry] + default = 'crates-io' + "#, + ); + let _alternative = RegistryBuilder::new().alternative().http_api().build(); + + cargo_process("yank foo@0.0.1") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[YANK] foo@0.0.1 + +"#]]) + .run(); +} + +#[cargo_test] +fn yank_with_default_alternative() { + // verifies that no error is given when registry.default is an alt registry. + let crates_io = setup_replacement( + r#" + [source.crates-io] + replace-with = 'alternative' + + [registry] + default = 'alternative' + "#, + ); + let _alternative = RegistryBuilder::new().alternative().http_api().build(); + + cargo_process("yank foo@0.0.1") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[YANK] foo@0.0.1 + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_with_replacement() { + // verifies that the crates.io token is not sent to a replacement registry during publish. + let crates_io = setup_replacement( + r#" + [source.crates-io] + replace-with = 'alternative' + "#, + ); + let _alternative = RegistryBuilder::new() + .alternative() + .http_api() + .no_configure_token() + .build(); + + // Publish bar only to alternative. This tests that the publish verification build + // does uses the source replacement. + Package::new("bar", "1.0.0").alternative(true).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + license = "MIT" + description = "foo" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Verifies that the crates.io index is used to find the publishing endpoint + // and that the crate is sent to crates.io. The source replacement is only used + // for the verification step. + p.cargo("publish --registry crates-io") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[UPDATING] `alternative` index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `alternative`) +[COMPILING] bar v1.0.0 +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[UPLOADED] foo v0.0.1 to registry `crates-io` +[NOTE] waiting for `foo v0.0.1` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.0.1 at registry `crates-io` + +"#]]) + .run(); +} + +#[cargo_test] +fn undefined_default() { + // verifies that no error is given when registry.default is used. + let crates_io = setup_replacement( + r#" + [registry] + default = 'undefined' + "#, + ); + + cargo_process("yank foo@0.0.1") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[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" + edition = "2015" + [dependencies.bar] + version = "0.0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .replace_crates_io(crates_io.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] `using-registry-url` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `using-registry-url`) +[CHECKING] bar v0.0.1 +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn source_replacement_with_no_package_in_directoy() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + bar = { version = "^0.8.9" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + let root = paths::root(); + t!(fs::create_dir(&root.join("vendor"))); + + let crates_io = setup_replacement(&format!( + r#" + [source.crates-io] + replace-with = "vendored-sources" + + [source.vendored-sources] + directory = "vendor" + "# + )); + + p.cargo("build") + .replace_crates_io(crates_io.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no matching package named `bar` found +location searched: directory source `[ROOT]/vendor` (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/ssh.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/ssh.rs new file mode 100644 index 000000000..ac2b9596c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/ssh.rs @@ -0,0 +1,635 @@ +//! Network tests for SSH connections. +//! +//! Note that these tests will generally require setting `CARGO_CONTAINER_TESTS` +//! or `CARGO_PUBLIC_NETWORK_TESTS`. +//! +//! NOTE: The container tests almost certainly won't work on Windows. + +use std::fs; +use std::io::Write; +use std::path::PathBuf; + +use cargo_test_support::containers::{Container, ContainerHandle, MkFile}; +use cargo_test_support::git::cargo_uses_gitoxide; +use cargo_test_support::prelude::*; +use cargo_test_support::{paths, process, project, str, Project}; + +fn ssh_repo_url(container: &ContainerHandle, name: &str) -> String { + let port = container.port_mappings[&22]; + format!("ssh://testuser@127.0.0.1:{port}/repos/{name}.git") +} + +/// The path to the client's private key. +fn key_path() -> PathBuf { + paths::home().join(".ssh/id_ed25519") +} + +/// Generates the SSH keys for authenticating into the container. +fn gen_ssh_keys() -> String { + let path = key_path(); + process("ssh-keygen") + .args(&["-t", "ed25519", "-N", "", "-f"]) + .arg(&path) + .exec_with_output() + .unwrap(); + let pub_key = path.with_extension("pub"); + fs::read_to_string(pub_key).unwrap() +} + +/// Handler for running ssh-agent for SSH authentication. +/// +/// Be sure to set `SSH_AUTH_SOCK` when running a process in order to use the +/// agent. Keys will need to be copied into the container with the +/// `authorized_keys()` method. +struct Agent { + sock: PathBuf, + pid: String, + ssh_dir: PathBuf, + pub_key: String, +} + +impl Agent { + fn launch() -> Agent { + let ssh_dir = paths::home().join(".ssh"); + fs::create_dir(&ssh_dir).unwrap(); + let pub_key = gen_ssh_keys(); + + let sock = paths::root().join("agent"); + let output = process("ssh-agent") + .args(&["-s", "-a"]) + .arg(&sock) + .exec_with_output() + .unwrap(); + let stdout = std::str::from_utf8(&output.stdout).unwrap(); + let start = stdout.find("SSH_AGENT_PID=").unwrap() + 14; + let end = &stdout[start..].find(';').unwrap(); + let pid = (&stdout[start..start + end]).to_string(); + eprintln!("SSH_AGENT_PID={pid}"); + process("ssh-add") + .arg(key_path()) + .env("SSH_AUTH_SOCK", &sock) + .exec_with_output() + .unwrap(); + Agent { + sock, + pid, + ssh_dir, + pub_key, + } + } + + /// Returns a `MkFile` which can be passed into the `Container` builder to + /// copy an `authorized_keys` file containing this agent's public key. + fn authorized_keys(&self) -> MkFile { + MkFile::path("home/testuser/.ssh/authorized_keys") + .contents(self.pub_key.as_bytes()) + .mode(0o600) + .uid(100) + .gid(101) + } +} + +impl Drop for Agent { + fn drop(&mut self) { + if let Err(e) = process("ssh-agent") + .args(&["-k", "-a"]) + .arg(&self.sock) + .env("SSH_AGENT_PID", &self.pid) + .exec_with_output() + { + eprintln!("failed to stop ssh-agent: {e:?}"); + } + } +} + +/// Common project used for several tests. +fn foo_bar_project(url: &str) -> Project { + project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {{ git = "{url}" }} + "# + ), + ) + .file("src/lib.rs", "") + .build() +} + +#[cargo_test(container_test)] +fn no_known_host() { + // When host is not known, it should show an error. + let sshd = Container::new("sshd").launch(); + let url = ssh_repo_url(&sshd, "bar"); + let p = foo_bar_project(&url); + p.cargo("fetch") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git` +[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update ssh://testuser@127.0.0.1:[..]/repos/bar.git + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: + [ERROR] unknown SSH host key + The SSH host key for `[127.0.0.1]:[..]` is not known and cannot be validated. + + To resolve this issue, add the host key to the `net.ssh.known-hosts` array in your Cargo configuration (such as [ROOT]/home/.cargo/config.toml) or in your OpenSSH known_hosts file at [ROOT]/home/.ssh/known_hosts + + The key to add is: + + [127.0.0.1]:[..] ecdsa-sha2-nistp256 AAAA[..] + + The ECDSA key fingerprint is: SHA256:[..] + This fingerprint should be validated with the server administrator that it is correct. + + See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts for more information. + +"#]]) + .run(); +} + +#[cargo_test(container_test)] +fn known_host_works() { + // The key displayed in the error message should work when added to known_hosts. + let agent = Agent::launch(); + let sshd = Container::new("sshd") + .file(agent.authorized_keys()) + .launch(); + let url = ssh_repo_url(&sshd, "bar"); + let p = foo_bar_project(&url); + let output = p + .cargo("fetch") + .env("SSH_AUTH_SOCK", &agent.sock) + .build_command() + .output() + .unwrap(); + let stderr = std::str::from_utf8(&output.stderr).unwrap(); + + // Validate the fingerprint while we're here. + let fingerprint = stderr + .lines() + .find_map(|line| line.strip_prefix(" The ECDSA key fingerprint is: ")) + .unwrap() + .trim(); + 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(); + // + let gen_finger = gen_finger.split_whitespace().nth(1).unwrap(); + assert_eq!(fingerprint, gen_finger); + + // Add the key to known_hosts, and try again. + let key = stderr + .lines() + .find(|line| line.starts_with(" [127.0.0.1]:")) + .unwrap() + .trim(); + fs::write(agent.ssh_dir.join("known_hosts"), key).unwrap(); + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &agent.sock) + .with_stderr_data(str![[r#" +[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); +} + +#[cargo_test(container_test)] +fn same_key_different_hostname() { + // The error message should mention if an identical key was found. + let agent = Agent::launch(); + let sshd = Container::new("sshd").launch(); + + let hostkey = sshd.read_file("/etc/ssh/ssh_host_ecdsa_key.pub"); + let known_hosts = format!("example.com {hostkey}"); + fs::write(agent.ssh_dir.join("known_hosts"), known_hosts).unwrap(); + + let url = ssh_repo_url(&sshd, "bar"); + let p = foo_bar_project(&url); + p.cargo("fetch") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git` +[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update ssh://testuser@127.0.0.1:[..]/repos/bar.git + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: + [ERROR] unknown SSH host key + The SSH host key for `[127.0.0.1]:[..]` is not known and cannot be validated. + + To resolve this issue, add the host key to the `net.ssh.known-hosts` array in your Cargo configuration (such as [ROOT]/home/.cargo/config.toml) or in your OpenSSH known_hosts file at [ROOT]/home/.ssh/known_hosts + + The key to add is: + + [127.0.0.1]:[..] ecdsa-sha2-nistp256 AAAA[..] + + The ECDSA key fingerprint is: SHA256:[..] + This fingerprint should be validated with the server administrator that it is correct. + Note: This host key was found, but is associated with a different host: + [ROOT]/home/.ssh/known_hosts line 1: example.com + + See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts for more information. + +"#]]) + .run(); +} + +#[cargo_test(container_test)] +fn known_host_without_port() { + // A known_host entry without a port should match a connection to a non-standard port. + let agent = Agent::launch(); + let sshd = Container::new("sshd") + .file(agent.authorized_keys()) + .launch(); + + let hostkey = sshd.read_file("/etc/ssh/ssh_host_ecdsa_key.pub"); + // The important part of this test is that this line does not have a port. + let known_hosts = format!("127.0.0.1 {hostkey}"); + fs::write(agent.ssh_dir.join("known_hosts"), known_hosts).unwrap(); + let url = ssh_repo_url(&sshd, "bar"); + let p = foo_bar_project(&url); + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &agent.sock) + .with_stderr_data(str![[r#" +[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); +} + +#[cargo_test(container_test)] +fn hostname_case_insensitive() { + // hostname checking should be case-insensitive. + let agent = Agent::launch(); + let sshd = Container::new("sshd") + .file(agent.authorized_keys()) + .launch(); + + // Consider using `gethostname-rs` instead? + let hostname = process("hostname").exec_with_output().unwrap(); + let hostname = std::str::from_utf8(&hostname.stdout).unwrap().trim(); + let inv_hostname = if hostname.chars().any(|c| c.is_lowercase()) { + hostname.to_uppercase() + } else { + // There should be *some* chars in the name. + assert!(hostname.chars().any(|c| c.is_uppercase())); + hostname.to_lowercase() + }; + eprintln!("converted {hostname} to {inv_hostname}"); + + let hostkey = sshd.read_file("/etc/ssh/ssh_host_ecdsa_key.pub"); + let known_hosts = format!("{inv_hostname} {hostkey}"); + fs::write(agent.ssh_dir.join("known_hosts"), known_hosts).unwrap(); + let port = sshd.port_mappings[&22]; + let url = format!("ssh://testuser@{hostname}:{port}/repos/bar.git"); + let p = foo_bar_project(&url); + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &agent.sock) + .with_stderr_data(&format!( + "\ +[UPDATING] git repository `ssh://testuser@{hostname}:{port}/repos/bar.git` +[LOCKING] 1 package to latest compatible version +" + )) + .run(); +} + +#[cargo_test(container_test)] +fn invalid_key_error() { + // An error when a known_host value doesn't match. + let agent = Agent::launch(); + let sshd = Container::new("sshd") + .file(agent.authorized_keys()) + .launch(); + + let port = sshd.port_mappings[&22]; + let known_hosts = format!( + "[127.0.0.1]:{port} ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLqLMclVr7MDuaVsm3sEnnq2OrGxTFiHSw90wd6N14BU8xVC9cZldC3rJ58Wmw6bEVKPjk7foNG0lHwS5bCKX+U=\n" + ); + fs::write(agent.ssh_dir.join("known_hosts"), known_hosts).unwrap(); + let url = ssh_repo_url(&sshd, "bar"); + let p = foo_bar_project(&url); + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &agent.sock) + .with_status(101) + .with_stderr_data(&format!("\ +[UPDATING] git repository `ssh://testuser@127.0.0.1:{port}/repos/bar.git` +[ERROR] failed to get `bar` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bar` + +Caused by: + Unable to update ssh://testuser@127.0.0.1:{port}/repos/bar.git + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bar-[HASH] + +Caused by: + [ERROR] SSH host key has changed for `[127.0.0.1]:{port}` + ********************************* + * WARNING: HOST KEY HAS CHANGED * + ********************************* + This may be caused by a man-in-the-middle attack, or the server may have changed its host key. + + The ECDSA fingerprint for the key from the remote host is: + SHA256:[..] + + You are strongly encouraged to contact the server administrator for `[127.0.0.1]:{port}` to verify that this new key is correct. + + If you can verify that the server has a new key, you can resolve this error by removing the old ecdsa-sha2-nistp256 key for `[127.0.0.1]:{port}` located at [ROOT]/home/.ssh/known_hosts line 1, and adding the new key to the `net.ssh.known-hosts` array in your Cargo configuration (such as [ROOT]/home/.cargo/config.toml) or in your OpenSSH known_hosts file at [ROOT]/home/.ssh/known_hosts + + The key provided by the remote host is: + + [127.0.0.1]:{port} ecdsa-sha2-nistp256 [..] + + See https://doc.rust-lang.org/stable/cargo/appendix/git-authentication.html#ssh-known-hosts for more information. +")) + .run(); + // Add the key, it should work even with the old key left behind. + let hostkey = sshd.read_file("/etc/ssh/ssh_host_ecdsa_key.pub"); + let known_hosts_path = agent.ssh_dir.join("known_hosts"); + let mut f = fs::OpenOptions::new() + .append(true) + .open(known_hosts_path) + .unwrap(); + write!(f, "[127.0.0.1]:{port} {hostkey}").unwrap(); + drop(f); + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &agent.sock) + .with_stderr_data(str![[r#" +[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); +} + +// For unknown reasons, this test occasionally fails on Windows with a +// LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE error: +// failed to start SSH session: Unable to exchange encryption keys; class=Ssh (23) +#[cargo_test(public_network_test, ignore_windows = "test is flaky on windows")] +fn invalid_github_key() { + // A key for github.com in known_hosts should override the built-in key. + // This uses a bogus key which should result in an error. + let ssh_dir = paths::home().join(".ssh"); + fs::create_dir(&ssh_dir).unwrap(); + let known_hosts = "\ + github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLqLMclVr7MDuaVsm3sEnnq2OrGxTFiHSw90wd6N14BU8xVC9cZldC3rJ58Wmw6bEVKPjk7foNG0lHwS5bCKX+U=\n\ + github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDgi+8rMcyFCBq5y7BXrb2aaYGhMjlU3QDy7YDvtNL5KSecYOsaqQHaXr87Bbx0EEkgbhK4kVMkmThlCoNITQS9Vc3zIMQ+Tg6+O4qXx719uCzywl50Tb5tDqPGMj54jcq3VUiu/dvse0yeehyvzoPNWewgGWLx11KI4A4wOwMnc6guhculEWe9DjGEjUQ34lPbmdfu/Hza7ZVu/RhgF/wc43uzXWB2KpMEqtuY1SgRlCZqTASoEtfKZi0AuM7AEdOwE5aTotS4CQZHWimb1bMFpF4DAq92CZ8Jhrm4rWETbO29WmjviCJEA3KNQyd3oA7H9AE9z/22PJaVEmjiZZ+wyLgwyIpOlsnHYNEdGeQMQ4SgLRkARLwcnKmByv1AAxsBW4LI3Os4FpwxVPdXHcBebydtvxIsbtUVkkq99nbsIlnSRFSTvb0alrdzRuKTdWpHtN1v9hagFqmeCx/kJfH76NXYBbtaWZhSOnxfEbhLYuOb+IS4jYzHAIkzy9FjVuk=\n\ + ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEeMB6BUAW6FfvfLxRO3kGASe0yXnrRT4kpqncsup2b2\n"; + fs::write(ssh_dir.join("known_hosts"), known_hosts).unwrap(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bitflags = { git = "ssh://git@github.com/rust-lang/bitflags.git", tag = "1.3.2" } + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("fetch") + .with_status(101) + .with_stderr_data(if cargo_uses_gitoxide() { + str![[r#" +... + git@github.com: Permission denied (publickey). +... +"#]] + } else { + str![[r#" +... + [ERROR] SSH host key has changed for `github.com` +... +"#]] + }) + .run(); +} + +// For unknown reasons, this test occasionally fails on Windows with a +// LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE error: +// failed to start SSH session: Unable to exchange encryption keys; class=Ssh (23) +#[cargo_test(public_network_test, ignore_windows = "test is flaky on windows")] +fn bundled_github_works() { + // The bundled key for github.com works. + // + // Use a bogus auth sock to force an authentication error. + // On Windows, if the agent service is running, it could allow a + // successful authentication. + // + // If the bundled hostkey did not work, it would result in an "unknown SSH + // host key" instead. + let bogus_auth_sock = paths::home().join("ssh_auth_sock"); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bitflags = { git = "ssh://git@github.com/rust-lang/bitflags.git", tag = "1.3.2" } + "#, + ) + .file("src/lib.rs", "") + .build(); + let expected = if cargo_uses_gitoxide() { + str![[r#" +[UPDATING] git repository `ssh://git@github.com/rust-lang/bitflags.git` +[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bitflags` + +Caused by: + Unable to update ssh://git@github.com/rust-lang/bitflags.git?tag=1.3.2 + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH] + +Caused by: + failed to authenticate when downloading repository + + * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect + + if the git CLI succeeds then `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: +[CREDENTIAL]s provided for "ssh://git@github.com/rust-lang/bitflags.git" were not accepted by the remote + +Caused by: + git@github.com: Permission denied (publickey). + +"#]] + } else { + str![[r#" +[UPDATING] git repository `ssh://git@github.com/rust-lang/bitflags.git` +[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bitflags` + +Caused by: + Unable to update ssh://git@github.com/rust-lang/bitflags.git?tag=1.3.2 + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH] + +Caused by: + failed to authenticate when downloading repository + + * attempted ssh-agent authentication, but no usernames succeeded: `git` + + if the git CLI succeeds then `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: + no authentication methods succeeded + +"#]] + }; + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &bogus_auth_sock) + .with_status(101) + .with_stderr_data(expected) + .run(); + + let expected = if cargo_uses_gitoxide() { + str![[r#" +[UPDATING] git repository `ssh://git@github.com:22/rust-lang/bitflags.git` +[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bitflags` + +Caused by: + Unable to update ssh://git@github.com:22/rust-lang/bitflags.git?tag=1.3.2 + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH] + +Caused by: + failed to authenticate when downloading repository + + * attempted to find username/password via `credential.helper`, but maybe the found credentials were incorrect + + if the git CLI succeeds then `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: +[CREDENTIAL]s provided for "ssh://git@github.com:22/rust-lang/bitflags.git" were not accepted by the remote + +Caused by: + git@github.com: Permission denied (publickey). + +"#]] + } else { + str![[r#" +[UPDATING] git repository `ssh://git@github.com:22/rust-lang/bitflags.git` +[ERROR] failed to get `bitflags` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `bitflags` + +Caused by: + Unable to update ssh://git@github.com:22/rust-lang/bitflags.git?tag=1.3.2 + +Caused by: + failed to clone into: [ROOT]/home/.cargo/git/db/bitflags-[HASH] + +Caused by: + failed to authenticate when downloading repository + + * attempted ssh-agent authentication, but no usernames succeeded: `git` + + if the git CLI succeeds then `net.git-fetch-with-cli` may help here + https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli + +Caused by: + no authentication methods succeeded + +"#]] + }; + + // Explicit :22 should also work with bundled. + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bitflags = { git = "ssh://git@github.com:22/rust-lang/bitflags.git", tag = "1.3.2" } + "#, + ); + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &bogus_auth_sock) + .with_status(101) + .with_stderr_data(expected) + .run(); +} + +#[cargo_test(container_test)] +fn ssh_key_in_config() { + // known_host in config works. + let agent = Agent::launch(); + let sshd = Container::new("sshd") + .file(agent.authorized_keys()) + .launch(); + let hostkey = sshd.read_file("/etc/ssh/ssh_host_ecdsa_key.pub"); + let url = ssh_repo_url(&sshd, "bar"); + let p = foo_bar_project(&url); + p.change_file( + ".cargo/config.toml", + &format!( + r#" + [net.ssh] + known-hosts = ['127.0.0.1 {}'] + "#, + hostkey.trim() + ), + ); + p.cargo("fetch") + .env("SSH_AUTH_SOCK", &agent.sock) + .with_stderr_data(str![[r#" +[UPDATING] git repository `ssh://testuser@127.0.0.1:[..]/repos/bar.git` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/standard_lib.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/standard_lib.rs new file mode 100644 index 000000000..7c56e5523 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/standard_lib.rs @@ -0,0 +1,872 @@ +//! Tests for building the standard library (-Zbuild-std). +//! +//! These tests all use a "mock" standard library so that we don't have to +//! rebuild the real one. There is a separate integration test `build-std` +//! which builds the real thing, but that should be avoided if possible. + +use std::path::{Path, PathBuf}; + +use cargo_test_support::cross_compile; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::ProjectBuilder; +use cargo_test_support::{paths, project, rustc_host, str, Execs}; + +struct Setup { + rustc_wrapper: PathBuf, + real_sysroot: String, +} + +fn setup() -> Setup { + // Our mock sysroot requires a few packages from crates.io, so make sure + // they're "published" to crates.io. Also edit their code a bit to make sure + // that they have access to our custom crates with custom apis. + Package::new("registry-dep-using-core", "1.0.0") + .file( + "src/lib.rs", + " + #![no_std] + + #[cfg(feature = \"mockbuild\")] + pub fn custom_api() { + } + + #[cfg(not(feature = \"mockbuild\"))] + pub fn non_sysroot_api() { + core::custom_api(); + } + ", + ) + .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) + .feature("mockbuild", &["rustc-std-workspace-core"]) + .publish(); + Package::new("registry-dep-using-alloc", "1.0.0") + .file( + "src/lib.rs", + " + #![no_std] + + extern crate alloc; + + #[cfg(feature = \"mockbuild\")] + pub fn custom_api() { + } + + #[cfg(not(feature = \"mockbuild\"))] + pub fn non_sysroot_api() { + core::custom_api(); + alloc::custom_api(); + } + ", + ) + .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) + .add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true)) + .feature( + "mockbuild", + &["rustc-std-workspace-core", "rustc-std-workspace-alloc"], + ) + .publish(); + Package::new("registry-dep-using-std", "1.0.0") + .file( + "src/lib.rs", + " + #[cfg(feature = \"mockbuild\")] + pub fn custom_api() { + } + + #[cfg(not(feature = \"mockbuild\"))] + pub fn non_sysroot_api() { + std::custom_api(); + } + ", + ) + .add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true)) + .feature("mockbuild", &["rustc-std-workspace-std"]) + .publish(); + + let p = ProjectBuilder::new(paths::root().join("rustc-wrapper")) + .file( + "src/main.rs", + r#" + use std::process::Command; + use std::env; + fn main() { + let mut args = env::args().skip(1).collect::>(); + + let is_sysroot_crate = env::var_os("RUSTC_BOOTSTRAP").is_some(); + if is_sysroot_crate { + args.push("--sysroot".to_string()); + args.push(env::var("REAL_SYSROOT").unwrap()); + } else if args.iter().any(|arg| arg == "--target") { + // build-std target unit + // + // This `--sysroot` is here to disable the sysroot lookup, + // to ensure nothing is required. + // See https://github.com/rust-lang/wg-cargo-std-aware/issues/31 + // for more information on this. + // + // FIXME: this is broken on x86_64-unknown-linux-gnu + // due to https://github.com/rust-lang/rust/pull/124129, + // because it requires lld in the sysroot. See + // https://github.com/rust-lang/rust/issues/125246 for + // more information. + // args.push("--sysroot".to_string()); + // args.push("/path/to/nowhere".to_string()); + } else { + // host unit, do not use sysroot + } + + let ret = Command::new(&args[0]).args(&args[1..]).status().unwrap(); + std::process::exit(ret.code().unwrap_or(1)); + } + "#, + ) + .build(); + p.cargo("build").run(); + + Setup { + rustc_wrapper: p.bin("foo"), + real_sysroot: paths::sysroot(), + } +} + +fn enable_build_std(e: &mut Execs, setup: &Setup) { + // First up, force Cargo to use our "mock sysroot" which mimics what + // libstd looks like upstream. + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/testsuite/mock-std/library"); + e.env("__CARGO_TESTS_ONLY_SRC_ROOT", &root); + + e.masquerade_as_nightly_cargo(&["build-std"]); + + // We do various shenanigans to ensure our "mock sysroot" actually links + // with the real sysroot, so we don't have to actually recompile std for + // each test. Perform all that logic here, namely: + // + // * RUSTC_WRAPPER - uses our shim executable built above to control rustc + // * REAL_SYSROOT - used by the shim executable to swap out to the real + // sysroot temporarily for some compilations + // * RUST{,DOC}FLAGS - an extra `-L` argument to ensure we can always load + // crates from the sysroot, but only indirectly through other crates. + e.env("RUSTC_WRAPPER", &setup.rustc_wrapper); + e.env("REAL_SYSROOT", &setup.real_sysroot); + let libdir = format!("/lib/rustlib/{}/lib", rustc_host()); + e.env( + "RUSTFLAGS", + format!("-Ldependency={}{}", setup.real_sysroot, libdir), + ); + e.env( + "RUSTDOCFLAGS", + format!("-Ldependency={}{}", setup.real_sysroot, libdir), + ); +} + +// Helper methods used in the tests below +trait BuildStd: Sized { + fn build_std(&mut self, setup: &Setup) -> &mut Self; + fn build_std_arg(&mut self, setup: &Setup, arg: &str) -> &mut Self; + fn target_host(&mut self) -> &mut Self; +} + +impl BuildStd for Execs { + fn build_std(&mut self, setup: &Setup) -> &mut Self { + enable_build_std(self, setup); + self.arg("-Zbuild-std"); + self + } + + fn build_std_arg(&mut self, setup: &Setup, arg: &str) -> &mut Self { + enable_build_std(self, setup); + self.arg(format!("-Zbuild-std={}", arg)); + self + } + + fn target_host(&mut self) -> &mut Self { + self.arg("--target").arg(rustc_host()); + self + } +} + +#[cargo_test(build_std_mock)] +fn basic() { + let setup = setup(); + + let p = project() + .file( + "src/main.rs", + " + fn main() { + std::custom_api(); + foo::f(); + } + + #[test] + fn smoke_bin_unit() { + std::custom_api(); + foo::f(); + } + ", + ) + .file( + "src/lib.rs", + " + extern crate alloc; + extern crate proc_macro; + + /// ``` + /// foo::f(); + /// ``` + pub fn f() { + core::custom_api(); + std::custom_api(); + alloc::custom_api(); + proc_macro::custom_api(); + } + + #[test] + fn smoke_lib_unit() { + std::custom_api(); + f(); + } + ", + ) + .file( + "tests/smoke.rs", + " + #[test] + fn smoke_integration() { + std::custom_api(); + foo::f(); + } + ", + ) + .build(); + + p.cargo("check -v").build_std(&setup).target_host().run(); + p.cargo("build").build_std(&setup).target_host().run(); + p.cargo("run").build_std(&setup).target_host().run(); + p.cargo("test").build_std(&setup).target_host().run(); +} + +#[cargo_test(build_std_mock)] +fn shared_std_dependency_rebuild() { + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let setup = setup(); + let p = project() + .file( + "Cargo.toml", + format!( + " + [package] + name = \"foo\" + version = \"0.1.0\" + edition = \"2021\" + + [build-dependencies] + dep_test = {{ path = \"{}/tests/testsuite/mock-std/dep_test\" }} + ", + manifest_dir.replace('\\', "/") + ) + .as_str(), + ) + .file( + "src/main.rs", + r#" + fn main() { + println!("Hello, World!"); + } + "#, + ) + .file( + "build.rs", + r#" + fn main() { + println!("cargo::rerun-if-changed=build.rs"); + } + "#, + ) + .build(); + + p.cargo("build -v") + .build_std(&setup) + .target_host() + .with_stderr_data(str![[r#" +... +[RUNNING] `[..] rustc --crate-name dep_test [..]` +... +[RUNNING] `[..] rustc --crate-name dep_test [..]` +... +"#]]) + .run(); + + // TODO: Because of the way in which std is resolved, it's mandatory that this is left commented + // out as it will fail. This case should result in `dep_test` only being built once, however + // it's still being built twice. This is a bug. + // + // p.cargo("build -v") + // .build_std(&setup) + // .with_stderr_does_not_contain(str![[r#" + //... + //[RUNNING] `[..] rustc --crate-name dep_test [..]` + //... + //[RUNNING] `[..] rustc --crate-name dep_test [..]` + //... + //"#]]) + // .run(); +} + +#[cargo_test(build_std_mock)] +fn simple_lib_std() { + let setup = setup(); + + let p = project().file("src/lib.rs", "").build(); + p.cargo("build -v") + .build_std(&setup) + .target_host() + .with_stderr_data(str![[r#" +... +[RUNNING] `[..] rustc --crate-name std [..]` +... +"#]]) + .run(); + // Check freshness. + p.change_file("src/lib.rs", " "); + p.cargo("build -v") + .build_std(&setup) + .target_host() + .with_stderr_data(str![[r#" +... +[FRESH] std v0.1.0 ([..]/tests/testsuite/mock-std/library/std) +... +"#]]) + .run(); +} + +#[cargo_test(build_std_mock)] +fn simple_bin_std() { + let setup = setup(); + + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("run -v").build_std(&setup).target_host().run(); +} + +#[cargo_test(build_std_mock)] +fn lib_nostd() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + #![no_std] + pub fn foo() { + assert_eq!(u8::MIN, 0); + } + "#, + ) + .build(); + p.cargo("build -v --lib") + .build_std_arg(&setup, "core") + .target_host() + .with_stderr_does_not_contain("[..]libstd[..]") + .run(); +} + +#[cargo_test(build_std_mock)] +fn check_core() { + let setup = setup(); + + let p = project() + .file("src/lib.rs", "#![no_std] fn unused_fn() {}") + .build(); + + p.cargo("check -v") + .build_std_arg(&setup, "core") + .target_host() + .with_stderr_data(str![[r#" +... +[WARNING] function `unused_fn` is never used +... +"#]]) + .run(); +} + +#[cargo_test(build_std_mock)] +fn build_std_with_no_arg_for_core_only_target() { + let target = "aarch64-unknown-none"; + if !cross_compile::requires_target_installed(target) { + return; + } + + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + #![no_std] + pub fn foo() { + assert_eq!(u8::MIN, 0); + } + "#, + ) + .build(); + + p.cargo("build -v") + .arg("--target") + .arg(target) + .build_std(&setup) + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] registry-dep-using-std v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] registry-dep-using-core v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] registry-dep-using-alloc v1.0.0 (registry `dummy-registry`) +[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins) +[COMPILING] core v0.1.0 ([..]/library/core) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..] rustc --crate-name core [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..] rustc --crate-name foo [..]--target aarch64-unknown-none[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + p.cargo("clean").run(); + + // Also work for a mix of std and core-only targets, + // though not sure how common it is... + // + // Note that we don't download std dependencies for the second call + // because `-Zbuild-std` downloads them all also when building for core only. + p.cargo("build -v") + .arg("--target") + .arg(target) + .target_host() + .build_std(&setup) + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[COMPILING] core v0.1.0 ([..]/library/core) +[COMPILING] dep_test v0.1.0 ([..]/dep_test) +[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins) +[COMPILING] proc_macro v0.1.0 ([..]/library/proc_macro) +[COMPILING] panic_unwind v0.1.0 ([..]/library/panic_unwind) +[COMPILING] rustc-std-workspace-core v1.9.0 ([..]/library/rustc-std-workspace-core) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] registry-dep-using-core v1.0.0 +[COMPILING] alloc v0.1.0 ([..]/library/alloc) +[COMPILING] rustc-std-workspace-alloc v1.9.0 ([..]/library/rustc-std-workspace-alloc) +[COMPILING] registry-dep-using-alloc v1.0.0 +[COMPILING] std v0.1.0 ([..]/library/std) +[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..]rustc --crate-name core [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..]rustc --crate-name foo [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..]rustc --crate-name core [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name dep_test [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name proc_macro [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name panic_unwind [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name rustc_std_workspace_core [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name registry_dep_using_core [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name alloc [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name rustc_std_workspace_alloc [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name registry_dep_using_alloc [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name std [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name foo [..]--target [HOST_TARGET][..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test(build_std_mock)] +fn depend_same_as_std() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + pub fn f() { + registry_dep_using_core::non_sysroot_api(); + registry_dep_using_alloc::non_sysroot_api(); + registry_dep_using_std::non_sysroot_api(); + } + "#, + ) + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [dependencies] + registry-dep-using-core = "1.0" + registry-dep-using-alloc = "1.0" + registry-dep-using-std = "1.0" + "#, + ) + .build(); + + p.cargo("build -v").build_std(&setup).target_host().run(); +} + +#[cargo_test(build_std_mock)] +fn test() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + #[cfg(test)] + mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } + } + "#, + ) + .build(); + + p.cargo("test -v") + .build_std(&setup) + .target_host() + .with_stdout_data(str![[r#" + +running 1 test +test tests::it_works ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .run(); +} + +#[cargo_test(build_std_mock)] +fn target_proc_macro() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + extern crate proc_macro; + pub fn f() { + let _ts = proc_macro::TokenStream::new(); + } + "#, + ) + .build(); + + p.cargo("build -v").build_std(&setup).target_host().run(); +} + +#[cargo_test(build_std_mock)] +fn bench() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + #![feature(test)] + extern crate test; + + #[bench] + fn b1(b: &mut test::Bencher) { + b.iter(|| ()) + } + "#, + ) + .build(); + + p.cargo("bench -v").build_std(&setup).target_host().run(); +} + +#[cargo_test(build_std_mock)] +fn doc() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + /// Doc + pub fn f() -> Result<(), ()> {Ok(())} + "#, + ) + .build(); + + p.cargo("doc -v").build_std(&setup).target_host().run(); +} + +#[cargo_test(build_std_mock)] +fn check_std() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + " + extern crate core; + extern crate alloc; + extern crate proc_macro; + pub fn f() {} + ", + ) + .file("src/main.rs", "fn main() {}") + .file( + "tests/t1.rs", + r#" + #[test] + fn t1() { + assert_eq!(1, 2); + } + "#, + ) + .build(); + + p.cargo("check -v --all-targets") + .build_std(&setup) + .target_host() + .run(); + p.cargo("check -v --all-targets --profile=test") + .build_std(&setup) + .target_host() + .run(); +} + +#[cargo_test(build_std_mock)] +fn doctest() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + /// Doc + /// ``` + /// std::custom_api(); + /// ``` + pub fn f() {} + "#, + ) + .build(); + + p.cargo("test --doc -v -Zdoctest-xcompile") + .build_std(&setup) + .with_stdout_data(str![[r#" + +running 1 test +test src/lib.rs - f (line 3) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .target_host() + .run(); +} + +#[cargo_test(build_std_mock)] +fn no_implicit_alloc() { + // Demonstrate that alloc is not implicitly in scope. + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + pub fn f() { + let _: Vec = alloc::vec::Vec::new(); + } + "#, + ) + .build(); + + p.cargo("build -v") + .build_std(&setup) + .target_host() + .with_stderr_data(str![[r#" +... +error[E0433]: failed to resolve[..]`alloc` +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test(build_std_mock)] +fn macro_expanded_shadow() { + // This tests a bug caused by the previous use of `--extern` to directly + // load sysroot crates. This necessitated the switch to `--sysroot` to + // retain existing behavior. See + // https://github.com/rust-lang/wg-cargo-std-aware/issues/40 for more + // detail. + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + macro_rules! a { + () => (extern crate std as alloc;) + } + a!(); + "#, + ) + .build(); + + p.cargo("build -v").build_std(&setup).target_host().run(); +} + +#[cargo_test(build_std_mock)] +fn ignores_incremental() { + // Incremental is not really needed for std, make sure it is disabled. + // Incremental also tends to have bugs that affect std libraries more than + // any other crate. + let setup = setup(); + + let p = project().file("src/lib.rs", "").build(); + p.cargo("build") + .env("CARGO_INCREMENTAL", "1") + .build_std(&setup) + .target_host() + .run(); + let incremental: Vec<_> = p + .glob(format!("target/{}/debug/incremental/*", rustc_host())) + .map(|e| e.unwrap()) + .collect(); + assert_eq!(incremental.len(), 1); + assert!(incremental[0] + .file_name() + .unwrap() + .to_str() + .unwrap() + .starts_with("foo-")); +} + +#[cargo_test(build_std_mock)] +fn cargo_config_injects_compiler_builtins() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + r#" + #![no_std] + pub fn foo() { + assert_eq!(u8::MIN, 0); + } + "#, + ) + .file( + ".cargo/config.toml", + r#" + [unstable] + build-std = ['core'] + "#, + ) + .build(); + let mut build = p.cargo("build -v --lib"); + enable_build_std(&mut build, &setup); + build + .target_host() + .with_stderr_does_not_contain("[..]libstd[..]") + .run(); +} + +#[cargo_test(build_std_mock)] +fn different_features() { + let setup = setup(); + + let p = project() + .file( + "src/lib.rs", + " + pub fn foo() { + std::conditional_function(); + } + ", + ) + .build(); + p.cargo("build") + .build_std(&setup) + .arg("-Zbuild-std-features=feature1") + .target_host() + .run(); +} + +#[cargo_test(build_std_mock)] +fn no_roots() { + // Checks for a bug where it would panic if there are no roots. + let setup = setup(); + + let p = project().file("tests/t1.rs", "").build(); + p.cargo("build") + .build_std(&setup) + .target_host() + .with_stderr_data(str![[r#" +... +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(build_std_mock)] +fn proc_macro_only() { + // Checks for a bug where it would panic if building a proc-macro only + let setup = setup(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + + [lib] + proc-macro = true + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("build") + .build_std(&setup) + .target_host() + .with_stderr_data(str![[r#" +... +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test(build_std_mock)] +fn fetch() { + let setup = setup(); + + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("fetch") + .build_std(&setup) + .target_host() + .with_stderr_contains("[DOWNLOADED] [..]") + .run(); + p.cargo("build") + .build_std(&setup) + .target_host() + .with_stderr_does_not_contain("[DOWNLOADED] [..]") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/test.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/test.rs new file mode 100644 index 000000000..e0ec17e43 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/test.rs @@ -0,0 +1,5591 @@ +//! Tests for the `cargo test` command. + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{ + basic_bin_manifest, basic_lib_manifest, basic_manifest, cargo_exe, project, str, +}; +use cargo_test_support::{cross_compile, paths}; +use cargo_test_support::{rustc_host, rustc_host_env, sleep_ms}; +use cargo_util::paths::dylib_path_envvar; + +#[cargo_test] +fn cargo_test_simple() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[test] + fn test_hello() { + assert_eq!(hello(), "hello") + } + "#, + ) + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test_hello ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_test_release() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + pub fn foo() { bar::bar(); } + + #[test] + fn test() { foo(); } + "#, + ) + .file( + "tests/test.rs", + r#" + extern crate foo; + + #[test] + fn test() { foo::foo(); } + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("test -v --release") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[RUNNING] `rustc [..]-C opt-level=3 [..]` +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C opt-level=3 [..]` +[RUNNING] `rustc [..]-C opt-level=3 [..]` +[RUNNING] `rustc [..]-C opt-level=3 [..]` +[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/release/deps/foo-[HASH][EXE]` +[RUNNING] `[ROOT]/foo/target/release/deps/test-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `rustdoc [..]--test src/lib.rs[..]` + +"#]]) + .with_stdout_data( + str![[r#" +test test ... ok +test test ... ok +running 0 tests +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn cargo_test_overflow_checks() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = [] + + [[bin]] + name = "foo" + + [profile.release] + overflow-checks = true + "#, + ) + .file( + "src/foo.rs", + r#" + use std::panic; + pub fn main() { + let r = panic::catch_unwind(|| { + [1, i32::MAX].iter().sum::(); + }); + assert!(r.is_err()); + } + "#, + ) + .build(); + + p.cargo("build --release").run(); + assert!(p.release_bin("foo").is_file()); + + p.process(&p.release_bin("foo")).with_stdout_data("").run(); +} + +#[cargo_test] +fn cargo_test_quiet_with_harness() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [[test]] + name = "foo" + path = "src/foo.rs" + harness = true + "#, + ) + .file( + "src/foo.rs", + r#" + fn main() {} + #[test] fn test_hello() {} + "#, + ) + .build(); + + p.cargo("test -q") + .with_stdout_data(str![[r#" + +running 1 test +. +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn cargo_test_quiet_no_harness() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [[bin]] + name = "foo" + test = false + + [[test]] + name = "foo" + path = "src/main.rs" + harness = false + "#, + ) + .file( + "src/main.rs", + r#" + fn main() {} + #[test] fn test_hello() {} + "#, + ) + .build(); + + p.cargo("test -q") + .with_stdout_data("") + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn cargo_doc_test_quiet() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file( + "src/lib.rs", + r#" + /// ``` + /// let result = foo::add(2, 3); + /// assert_eq!(result, 5); + /// ``` + pub fn add(a: i32, b: i32) -> i32 { + a + b + } + + /// ``` + /// let result = foo::div(10, 2); + /// assert_eq!(result, 5); + /// ``` + /// + /// # Panics + /// + /// The function panics if the second argument is zero. + /// + /// ```rust,should_panic + /// // panics on division by zero + /// foo::div(10, 0); + /// ``` + pub fn div(a: i32, b: i32) -> i32 { + if b == 0 { + panic!("Divide-by-zero error"); + } + + a / b + } + + #[test] fn test_hello() {} + "#, + ) + .build(); + + p.cargo("test -q") + .with_stdout_data(str![[r#" + +running 1 test +. +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 3 tests +... +test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .with_stderr_data("") + .run(); +} + +#[cargo_test] +fn cargo_test_verbose() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + fn main() {} + #[test] fn test_hello() {} + "#, + ) + .build(); + + p.cargo("test -v hello") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/main.rs [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE] hello` + +"#]]) + .with_stdout_data(str![[r#" +... +test test_hello ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn many_similar_names() { + let p = project() + .file( + "src/lib.rs", + " + pub fn foo() {} + #[test] fn lib_test() {} + ", + ) + .file( + "src/main.rs", + " + extern crate foo; + fn main() {} + #[test] fn bin_test() { foo::foo() } + ", + ) + .file( + "tests/foo.rs", + r#" + extern crate foo; + #[test] fn test_test() { foo::foo() } + "#, + ) + .build(); + + p.cargo("test -v") + .with_stdout_data( + str![[r#" +test bin_test ... ok +test lib_test ... ok +test test_test ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn cargo_test_failing_test_in_bin() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file( + "src/main.rs", + r#" + fn hello() -> &'static str { + "hello" + } + + pub fn main() { + println!("{}", hello()) + } + + #[test] + fn test_hello() { + assert_eq!(hello(), "nope", "NOPE!") + } + "#, + ) + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--bin foo` + +"#]]) + .with_stdout_data("...\n[..]NOPE![..]\n...") + .with_status(101) + .run(); +} + +#[cargo_test] +fn cargo_test_failing_test_in_test() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/main.rs", r#"pub fn main() { println!("hello"); }"#) + .file( + "tests/footest.rs", + r#"#[test] fn test_hello() { assert!(false, "FALSE!") }"#, + ) + .build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + + p.process(&p.bin("foo")) + .with_stdout_data(str![[r#" +hello + +"#]]) + .run(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] tests/footest.rs (target/debug/deps/footest-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test footest` + +"#]]) + .with_stdout_data( + str![[r#" +... +running 0 tests +... +running 1 test +test test_hello ... FAILED +... +[..]FALSE![..] +... + +"#]] + .unordered(), + ) + .with_status(101) + .run(); +} + +#[cargo_test] +fn cargo_test_failing_test_in_lib() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/lib.rs", + r#"#[test] fn test_hello() { assert!(false, "FALSE!") }"#, + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--lib` + +"#]]) + .with_stdout_data(str![[r#" +... +test test_hello ... FAILED +... +[..]FALSE![..] +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn test_with_lib_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "baz" + path = "src/main.rs" + "#, + ) + .file( + "src/lib.rs", + r#" + /// + /// ```rust + /// extern crate foo; + /// fn main() { + /// println!("{:?}", foo::foo()); + /// } + /// ``` + /// + pub fn foo(){} + #[test] fn lib_test() {} + "#, + ) + .file( + "src/main.rs", + " + #[allow(unused_extern_crates)] + extern crate foo; + + fn main() {} + + #[test] + fn bin_test() {} + ", + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] unittests src/main.rs (target/debug/deps/baz-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test lib_test ... ok +test bin_test ... ok +test [..] ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_with_deep_lib_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.bar] + path = "../bar" + "#, + ) + .file( + "src/lib.rs", + " + #[cfg(test)] + extern crate bar; + /// ``` + /// foo::foo(); + /// ``` + pub fn foo() {} + + #[test] + fn bar_test() { + bar::bar(); + } + ", + ) + .build(); + let _p2 = project() + .at("bar") + .file("Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("src/lib.rs", "pub fn bar() {} #[test] fn foo_test() {}") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test bar_test ... ok +test [..] ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn external_test_explicit() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[test]] + name = "test" + path = "src/test.rs" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn get_hello() -> &'static str { "Hello" } + + #[test] + fn internal_test() {} + "#, + ) + .file( + "src/test.rs", + r#" + extern crate foo; + + #[test] + fn external_test() { assert_eq!(foo::get_hello(), "Hello") } + "#, + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] src/test.rs (target/debug/deps/test-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test internal_test ... ok +test external_test ... ok +running 0 tests +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn external_test_named_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[test]] + name = "test" + "#, + ) + .file("src/lib.rs", "") + .file("tests/test.rs", "#[test] fn foo() {}") + .build(); + + p.cargo("test").run(); +} + +#[cargo_test] +fn external_test_implicit() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn get_hello() -> &'static str { "Hello" } + + #[test] + fn internal_test() {} + "#, + ) + .file( + "tests/external.rs", + r#" + extern crate foo; + + #[test] + fn external_test() { assert_eq!(foo::get_hello(), "Hello") } + "#, + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] tests/external.rs (target/debug/deps/external-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test internal_test ... ok +test external_test ... ok +running 0 tests +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn dont_run_examples() { + let p = project() + .file("src/lib.rs", "") + .file( + "examples/dont-run-me-i-will-fail.rs", + r#" + fn main() { panic!("Examples should not be run by 'cargo test'"); } + "#, + ) + .build(); + p.cargo("test").run(); +} + +#[cargo_test] +fn pass_through_escaped() { + let p = project() + .file( + "src/lib.rs", + " + /// ```rust + /// assert!(foo::foo()); + /// ``` + pub fn foo() -> bool { + true + } + + /// ```rust + /// assert!(!foo::bar()); + /// ``` + pub fn bar() -> bool { + false + } + + #[test] fn test_foo() { + assert!(foo()); + } + #[test] fn test_bar() { + assert!(!bar()); + } + ", + ) + .build(); + + p.cargo("test -- bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data(str![[r#" +... +running 1 test +test test_bar ... ok +... +"#]]) + .run(); + + p.cargo("test -- foo") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data(str![[r#" +... +running 1 test +test test_foo ... ok +... +"#]]) + .run(); + + p.cargo("test -- foo bar") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +running 2 tests +test test_foo ... ok +test test_bar ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +// Unlike `pass_through_escaped`, doctests won't run when using `testname` as an optimization +#[cargo_test] +fn pass_through_testname() { + let p = project() + .file( + "src/lib.rs", + " + /// ```rust + /// assert!(foo::foo()); + /// ``` + pub fn foo() -> bool { + true + } + + /// ```rust + /// assert!(!foo::bar()); + /// ``` + pub fn bar() -> bool { + false + } + + #[test] fn test_foo() { + assert!(foo()); + } + #[test] fn test_bar() { + assert!(!bar()); + } + ", + ) + .build(); + + p.cargo("test bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +running 1 test +test test_bar ... ok +... +"#]]) + .run(); + + p.cargo("test foo") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +running 1 test +test test_foo ... ok +... +"#]]) + .run(); + + p.cargo("test foo -- bar") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data( + str![[r#" +running 2 tests +test test_bar ... ok +test test_foo ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +// Regression test for running cargo-test twice with +// tests in an rlib +#[cargo_test] +fn cargo_test_twice() { + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/foo.rs", + r#" + #![crate_type = "rlib"] + + #[test] + fn dummy_test() { } + "#, + ) + .build(); + + for _ in 0..2 { + p.cargo("test").run(); + } +} + +#[cargo_test] +fn lib_bin_same_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + [[bin]] + name = "foo" + "#, + ) + .file("src/lib.rs", "#[test] fn lib_test() {}") + .file( + "src/main.rs", + " + #[allow(unused_extern_crates)] + extern crate foo; + + #[test] + fn bin_test() {} + ", + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] unittests src/main.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test lib_test ... ok +test bin_test ... ok +running 0 tests +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn lib_with_standard_name() { + let p = project() + .file("Cargo.toml", &basic_manifest("syntax", "0.0.1")) + .file( + "src/lib.rs", + " + /// ``` + /// syntax::foo(); + /// ``` + pub fn foo() {} + + #[test] + fn foo_test() {} + ", + ) + .file( + "tests/test.rs", + " + extern crate syntax; + + #[test] + fn test() { syntax::foo() } + ", + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] syntax v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/syntax-[HASH][EXE]) +[RUNNING] tests/test.rs (target/debug/deps/test-[HASH][EXE]) +[DOCTEST] syntax + +"#]]) + .with_stdout_data( + str![[r#" +test foo_test ... ok +test test ... ok +test [..] ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn lib_with_standard_name2() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "syntax" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "syntax" + test = false + doctest = false + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + " + extern crate syntax; + + fn main() {} + + #[test] + fn test() { syntax::foo() } + ", + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] syntax v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/syntax-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn lib_without_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "syntax" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + test = false + doctest = false + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + " + extern crate syntax; + + fn main() {} + + #[test] + fn test() { syntax::foo() } + ", + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] syntax v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/main.rs (target/debug/deps/syntax-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn bin_without_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "syntax" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + test = false + doctest = false + + [[bin]] + path = "src/main.rs" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + " + extern crate syntax; + + fn main() {} + + #[test] + fn test() { syntax::foo() } + ", + ) + .build(); + + p.cargo("test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + binary target bin.name is required + +"#]]) + .run(); +} + +#[cargo_test] +fn bench_without_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "syntax" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + test = false + doctest = false + + [[bench]] + path = "src/bench.rs" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + " + extern crate syntax; + + fn main() {} + + #[test] + fn test() { syntax::foo() } + ", + ) + .file( + "src/bench.rs", + " + #![feature(test)] + extern crate syntax; + extern crate test; + + #[bench] + fn external_bench(_b: &mut test::Bencher) {} + ", + ) + .build(); + + p.cargo("test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + benchmark target bench.name is required + +"#]]) + .run(); +} + +#[cargo_test] +fn test_without_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "syntax" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + test = false + doctest = false + + [[test]] + path = "src/test.rs" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn foo() {} + pub fn get_hello() -> &'static str { "Hello" } + "#, + ) + .file( + "src/main.rs", + " + extern crate syntax; + + fn main() {} + + #[test] + fn test() { syntax::foo() } + ", + ) + .file( + "src/test.rs", + r#" + extern crate syntax; + + #[test] + fn external_test() { assert_eq!(syntax::get_hello(), "Hello") } + "#, + ) + .build(); + + p.cargo("test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + test target test.name is required + +"#]]) + .run(); +} + +#[cargo_test] +fn example_without_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "syntax" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + test = false + doctest = false + + [[example]] + path = "examples/example.rs" + "#, + ) + .file("src/lib.rs", "pub fn foo() {}") + .file( + "src/main.rs", + " + extern crate syntax; + + fn main() {} + + #[test] + fn test() { syntax::foo() } + ", + ) + .file( + "examples/example.rs", + r#" + extern crate syntax; + + fn main() { + println!("example1"); + } + "#, + ) + .build(); + + p.cargo("test") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + example target example.name is required + +"#]]) + .run(); +} + +#[cargo_test] +fn bin_there_for_integration() { + let p = project() + .file( + "src/main.rs", + " + fn main() { std::process::exit(101); } + #[test] fn main_test() {} + ", + ) + .file( + "tests/foo.rs", + r#" + use std::process::Command; + #[test] + fn test_test() { + let status = Command::new("target/debug/foo").status().unwrap(); + assert_eq!(status.code(), Some(101)); + } + "#, + ) + .build(); + + p.cargo("test -v") + .with_stdout_data( + str![[r#" +test main_test ... ok +test test_test ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_dylib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + crate-type = ["dylib"] + + [dependencies.bar] + path = "bar" + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar as the_bar; + + pub fn bar() { the_bar::baz(); } + + #[test] + fn foo() { bar(); } + "#, + ) + .file( + "tests/test.rs", + r#" + extern crate foo as the_foo; + + #[test] + fn foo() { the_foo::bar(); } + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "bar" + crate-type = ["dylib"] + "#, + ) + .file("bar/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] tests/test.rs (target/debug/deps/test-[HASH][EXE]) + +"#]]) + .with_stdout_data( + str![[r#" +test foo ... ok +test foo ... ok +... +"#]] + .unordered(), + ) + .run(); + + p.root().move_into_the_past(); + p.cargo("test") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] tests/test.rs (target/debug/deps/test-[HASH][EXE]) + +"#]]) + .with_stdout_data( + str![[r#" +test foo ... ok +test foo ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_twice_with_build_cmd() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "#[test] fn foo() {}") + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test foo ... ok +running 0 tests +... +"#]] + .unordered(), + ) + .run(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test foo ... ok +running 0 tests +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_then_build() { + let p = project().file("src/lib.rs", "#[test] fn foo() {}").build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +test foo ... ok +running 0 tests +... +"#]] + .unordered(), + ) + .run(); + + p.cargo("build") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn test_no_run() { + let p = project() + .file("src/lib.rs", "#[test] fn foo() { panic!() }") + .build(); + + p.cargo("test --no-run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test] +fn test_no_run_emit_json() { + let p = project() + .file("src/lib.rs", "#[test] fn foo() { panic!() }") + .build(); + + p.cargo("test --no-run --message-format json") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn test_run_specific_bin_target() { + let prj = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name="bin1" + path="src/bin1.rs" + + [[bin]] + name="bin2" + path="src/bin2.rs" + "#, + ) + .file("src/bin1.rs", "#[test] fn test1() { }") + .file("src/bin2.rs", "#[test] fn test2() { }") + .build(); + + prj.cargo("test --bin bin2") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/bin2.rs (target/debug/deps/bin2-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test2 ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_run_implicit_bin_target() { + let prj = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name="mybin" + path="src/mybin.rs" + "#, + ) + .file( + "src/mybin.rs", + "#[test] fn test_in_bin() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .file("tests/mytest.rs", "#[test] fn test_in_test() { }") + .file("benches/mybench.rs", "#[test] fn test_in_bench() { }") + .file( + "examples/myexm.rs", + "#[test] fn test_in_exm() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .build(); + + prj.cargo("test --bins") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/mybin.rs (target/debug/deps/mybin-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test_in_bin ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_run_specific_test_target() { + let prj = project() + .file("src/bin/a.rs", "fn main() { }") + .file("src/bin/b.rs", "#[test] fn test_b() { } fn main() { }") + .file("tests/a.rs", "#[test] fn test_a() { }") + .file("tests/b.rs", "#[test] fn test_b() { }") + .build(); + + prj.cargo("test --test b") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/b.rs (target/debug/deps/b-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test_b ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_run_implicit_test_target() { + let prj = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name="mybin" + path="src/mybin.rs" + "#, + ) + .file( + "src/mybin.rs", + "#[test] fn test_in_bin() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .file("tests/mytest.rs", "#[test] fn test_in_test() { }") + .file("benches/mybench.rs", "#[test] fn test_in_bench() { }") + .file( + "examples/myexm.rs", + "fn main() { compile_error!(\"Don't build me!\"); }", + ) + .build(); + + prj.cargo("test --tests") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/mybin.rs (target/debug/deps/mybin-[HASH][EXE]) +[RUNNING] tests/mytest.rs (target/debug/deps/mytest-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test_in_test ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_run_implicit_bench_target() { + let prj = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name="mybin" + path="src/mybin.rs" + "#, + ) + .file( + "src/mybin.rs", + "#[test] fn test_in_bin() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .file("tests/mytest.rs", "#[test] fn test_in_test() { }") + .file("benches/mybench.rs", "#[test] fn test_in_bench() { }") + .file( + "examples/myexm.rs", + "fn main() { compile_error!(\"Don't build me!\"); }", + ) + .build(); + + prj.cargo("test --benches") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/mybin.rs (target/debug/deps/mybin-[HASH][EXE]) +[RUNNING] benches/mybench.rs (target/debug/deps/mybench-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +test test_in_bench ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_run_implicit_example_target() { + let prj = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "mybin" + path = "src/mybin.rs" + + [[example]] + name = "myexm1" + + [[example]] + name = "myexm2" + test = true + "#, + ) + .file( + "src/mybin.rs", + "#[test] fn test_in_bin() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .file("tests/mytest.rs", "#[test] fn test_in_test() { }") + .file("benches/mybench.rs", "#[test] fn test_in_bench() { }") + .file( + "examples/myexm1.rs", + "#[test] fn test_in_exm() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .file( + "examples/myexm2.rs", + "#[test] fn test_in_exm() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .build(); + + // Compiles myexm1 as normal, but does not run it. + prj.cargo("test -v") + .with_stderr_contains("[RUNNING] `rustc [..]myexm1.rs [..]--crate-type bin[..]") + .with_stderr_contains("[RUNNING] `rustc [..]myexm2.rs [..]--test[..]") + .with_stderr_does_not_contain("[RUNNING] [..]myexm1-[..]") + .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm2-[..]") + .run(); + + // Only tests myexm2. + prj.cargo("test --tests") + .with_stderr_does_not_contain("[RUNNING] [..]myexm1-[..]") + .with_stderr_contains("[RUNNING] [..]target/debug/examples/myexm2-[..]") + .run(); + + // Tests all examples. + prj.cargo("test --examples") + .with_stderr_data(str![[r#" +... +[RUNNING] unittests examples/myexm1.rs (target/debug/examples/myexm1-[HASH][EXE]) +[RUNNING] unittests examples/myexm2.rs (target/debug/examples/myexm2-[HASH][EXE]) +... +"#]]) + .run(); + + // Test an example, even without `test` set. + prj.cargo("test --example myexm1") + .with_stderr_data(str![[r#" +... +[RUNNING] unittests examples/myexm1.rs (target/debug/examples/myexm1-[HASH][EXE]) +... +"#]]) + .run(); + + // Tests all examples. + prj.cargo("test --all-targets") + .with_stderr_data(str![[r#" +... +[RUNNING] unittests examples/myexm1.rs (target/debug/examples/myexm1-[HASH][EXE]) +[RUNNING] unittests examples/myexm2.rs (target/debug/examples/myexm2-[HASH][EXE]) +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_filtered_excludes_compiling_examples() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "mybin" + test = false + "#, + ) + .file( + "src/lib.rs", + "#[cfg(test)] mod tests { #[test] fn test_in_lib() { } }", + ) + .file( + "src/bin/mybin.rs", + "#[test] fn test_in_bin() { } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .file("tests/mytest.rs", "#[test] fn test_in_test() { }") + .file( + "benches/mybench.rs", + "#[test] fn test_in_bench() { assert!(false) }", + ) + .file( + "examples/myexm1.rs", + "#[test] fn test_in_exm() { assert!(false) } + fn main() { panic!(\"Don't execute me!\"); }", + ) + .build(); + + p.cargo("test -v test_in_") + .with_stdout_data(str![[r#" + +running 1 test +test tests::test_in_lib ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test_in_test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .with_stderr_data( + str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --crate-type lib [..]` +[RUNNING] `rustc --crate-name foo --edition=2015 src/lib.rs [..] --test [..]` +[RUNNING] `rustc --crate-name mybin --edition=2015 src/bin/mybin.rs [..] --crate-type bin [..]` +[RUNNING] `rustc --crate-name mytest --edition=2015 tests/mytest.rs [..] --test [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE] test_in_` +[RUNNING] `[ROOT]/foo/target/debug/deps/mytest-[HASH][EXE] test_in_` + +"#]] + .unordered(), + ) + .with_stderr_does_not_contain("[RUNNING][..]rustc[..]myexm1[..]") + .with_stderr_does_not_contain("[RUNNING][..]deps/mybin-[..] test_in_") + .run(); +} + +#[cargo_test] +fn test_no_harness() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [[bin]] + name = "foo" + test = false + + [[test]] + name = "bar" + path = "foo.rs" + harness = false + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("foo.rs", "fn main() {}") + .build(); + + p.cargo("test -- --nocapture") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] foo.rs (target/debug/deps/bar-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test] +fn selective_testing() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "d1" + [dependencies.d2] + path = "d2" + + [lib] + name = "foo" + doctest = false + "#, + ) + .file("src/lib.rs", "") + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "d1" + doctest = false + "#, + ) + .file("d1/src/lib.rs", "") + .file( + "d1/src/main.rs", + "#[allow(unused_extern_crates)] extern crate d1; fn main() {}", + ) + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "d2" + doctest = false + "#, + ) + .file("d2/src/lib.rs", "") + .file( + "d2/src/main.rs", + "#[allow(unused_extern_crates)] extern crate d2; fn main() {}", + ); + let p = p.build(); + + println!("d1"); + p.cargo("test -p d1") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/d1-[HASH][EXE]) +[RUNNING] unittests src/main.rs (target/debug/deps/d1-[HASH][EXE]) + +"#]]) + .with_stdout_data( + str![[r#" +running 0 tests +running 0 tests +... +"#]] + .unordered(), + ) + .run(); + + println!("d2"); + p.cargo("test -p d2") + .with_stderr_data(str![[r#" +[COMPILING] d2 v0.0.1 ([ROOT]/foo/d2) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/d2-[HASH][EXE]) +[RUNNING] unittests src/main.rs (target/debug/deps/d2-[HASH][EXE]) + +"#]]) + .with_stdout_data( + str![[r#" +running 0 tests +running 0 tests +... +"#]] + .unordered(), + ) + .run(); + + println!("whole"); + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +running 0 tests +... +"#]]) + .run(); +} + +#[cargo_test] +fn almost_cyclic_but_not_quite() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies.b] + path = "b" + [dev-dependencies.c] + path = "c" + "#, + ) + .file( + "src/lib.rs", + r#" + #[cfg(test)] extern crate b; + #[cfg(test)] extern crate c; + "#, + ) + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.foo] + path = ".." + "#, + ) + .file( + "b/src/lib.rs", + r#" + #[allow(unused_extern_crates)] + extern crate foo; + "#, + ) + .file("c/Cargo.toml", &basic_manifest("c", "0.0.1")) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.cargo("test").run(); +} + +#[cargo_test] +fn build_then_selective_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.b] + path = "b" + "#, + ) + .file( + "src/lib.rs", + "#[allow(unused_extern_crates)] extern crate b;", + ) + .file( + "src/main.rs", + r#" + #[allow(unused_extern_crates)] + extern crate b; + #[allow(unused_extern_crates)] + extern crate foo; + fn main() {} + "#, + ) + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("build").run(); + p.root().move_into_the_past(); + p.cargo("test -p b").run(); +} + +#[cargo_test] +fn example_dev_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies.bar] + path = "bar" + "#, + ) + .file("src/lib.rs", "") + .file("examples/e1.rs", "extern crate bar; fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file( + "bar/src/lib.rs", + r#" + // make sure this file takes awhile to compile + macro_rules! f0( () => (1) ); + macro_rules! f1( () => ({(f0!()) + (f0!())}) ); + macro_rules! f2( () => ({(f1!()) + (f1!())}) ); + macro_rules! f3( () => ({(f2!()) + (f2!())}) ); + macro_rules! f4( () => ({(f3!()) + (f3!())}) ); + macro_rules! f5( () => ({(f4!()) + (f4!())}) ); + macro_rules! f6( () => ({(f5!()) + (f5!())}) ); + macro_rules! f7( () => ({(f6!()) + (f6!())}) ); + macro_rules! f8( () => ({(f7!()) + (f7!())}) ); + pub fn bar() { + f8!(); + } + "#, + ) + .build(); + p.cargo("test").run(); + p.cargo("run --example e1 --release -v").run(); +} + +#[cargo_test] +fn selective_testing_with_docs() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "d1" + "#, + ) + .file( + "src/lib.rs", + r#" + /// ``` + /// not valid rust + /// ``` + pub fn foo() {} + "#, + ) + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "d1" + path = "d1.rs" + "#, + ) + .file("d1/d1.rs", ""); + let p = p.build(); + + p.cargo("test -p d1") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] d1 v0.0.1 ([ROOT]/foo/d1) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests d1.rs (target/debug/deps/d1-[HASH][EXE]) +[DOCTEST] d1 + +"#]]) + .with_stdout_data( + str![[r#" +running 0 tests +running 0 tests +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn example_bin_same_name() { + let p = project() + .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#) + .file("examples/foo.rs", r#"fn main() { println!("example"); }"#) + .build(); + + p.cargo("test --no-run -v") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .run(); + + assert!(!p.bin("foo").is_file()); + assert!(p.bin("examples/foo").is_file()); + + p.process(&p.bin("examples/foo")) + .with_stdout_data(str![[r#" +example + +"#]]) + .run(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .with_stdout_data(str![[r#" +bin + +"#]]) + .run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn test_with_example_twice() { + let p = project() + .file("src/bin/foo.rs", r#"fn main() { println!("bin"); }"#) + .file("examples/foo.rs", r#"fn main() { println!("example"); }"#) + .build(); + + println!("first"); + p.cargo("test -v").run(); + assert!(p.bin("examples/foo").is_file()); + println!("second"); + p.cargo("test -v").run(); + assert!(p.bin("examples/foo").is_file()); +} + +#[cargo_test] +fn example_with_dev_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + test = false + doctest = false + + [dev-dependencies.a] + path = "a" + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + "#[allow(unused_extern_crates)] extern crate a; fn main() {}", + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("test -v") + .with_stderr_data( + str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[RUNNING] `rustc --crate-name foo [..]` +[RUNNING] `rustc --crate-name a [..]` +[RUNNING] `rustc --crate-name ex [..] --extern a=[..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn bin_is_preserved() { + let p = project() + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("build -v").run(); + assert!(p.bin("foo").is_file()); + + println!("test"); + p.cargo("test -v").run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn bad_example() { + let p = project().file("src/lib.rs", ""); + let p = p.build(); + + p.cargo("run --example foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no example target named `foo`. + + +"#]]) + .run(); + p.cargo("run --bin foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] no bin target named `foo`. + + +"#]]) + .run(); +} + +#[cargo_test] +fn doctest_feature() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + [features] + bar = [] + "#, + ) + .file( + "src/lib.rs", + r#" + /// ```rust + /// assert_eq!(foo::foo(), 1); + /// ``` + #[cfg(feature = "bar")] + pub fn foo() -> i32 { 1 } + "#, + ) + .build(); + + p.cargo("test --features bar") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +running 0 tests +test [..] ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn dashes_to_underscores() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo-bar", "0.0.1")) + .file( + "src/lib.rs", + r#" + /// ``` + /// assert_eq!(foo_bar::foo(), 1); + /// ``` + pub fn foo() -> i32 { 1 } + "#, + ) + .build(); + + p.cargo("test -v").run(); +} + +#[cargo_test] +fn doctest_dev_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies] + b = { path = "b" } + "#, + ) + .file( + "src/lib.rs", + r#" + /// ``` + /// extern crate b; + /// ``` + pub fn foo() {} + "#, + ) + .file("b/Cargo.toml", &basic_manifest("b", "0.0.1")) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("test -v").run(); +} + +#[cargo_test] +fn filter_no_doc_tests() { + let p = project() + .file( + "src/lib.rs", + r#" + /// ``` + /// extern crate b; + /// ``` + pub fn foo() {} + "#, + ) + .file("tests/foo.rs", "") + .build(); + + p.cargo("test --test=foo") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/foo.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" +... +running 0 tests +... +"#]]) + .run(); +} + +#[cargo_test] +fn dylib_doctest() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + crate-type = ["rlib", "dylib"] + test = false + "#, + ) + .file( + "src/lib.rs", + r#" + /// ``` + /// foo::foo(); + /// ``` + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[DOCTEST] foo + +"#]]) + .with_stdout_data(str![[r#" +... +test [..] ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn dylib_doctest2() { + // Can't doc-test dylibs, as they're statically linked together. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "foo" + crate-type = ["dylib"] + test = false + "#, + ) + .file( + "src/lib.rs", + r#" + /// ``` + /// foo::foo(); + /// ``` + pub fn foo() {} + "#, + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn cyclic_dev_dep_doc_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies] + bar = { path = "bar" } + "#, + ) + .file( + "src/lib.rs", + r#" + //! ``` + //! extern crate bar; + //! ``` + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = ".." } + "#, + ) + .file( + "bar/src/lib.rs", + r#" + #[allow(unused_extern_crates)] + extern crate foo; + "#, + ) + .build(); + p.cargo("test") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] bar v0.0.1 ([ROOT]/foo/bar) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data( + str![[r#" +running 0 tests +test [..] ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn dev_dep_with_build_script() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dev-dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file("examples/foo.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + build = "build.rs" + "#, + ) + .file("bar/src/lib.rs", "") + .file("bar/build.rs", "fn main() {}") + .build(); + p.cargo("test").run(); +} + +#[cargo_test] +fn no_fail_fast() { + let p = project() + .file( + "src/lib.rs", + r#" + pub fn add_one(x: i32) -> i32{ + x + 1 + } + + /// ```rust + /// use foo::sub_one; + /// assert_eq!(sub_one(101), 100); + /// ``` + pub fn sub_one(x: i32) -> i32{ + x - 1 + } + "#, + ) + .file( + "tests/test_add_one.rs", + r#" + extern crate foo; + use foo::*; + + #[test] + fn add_one_test() { + assert_eq!(add_one(1), 2); + } + + #[test] + fn fail_add_one_test() { + assert_eq!(add_one(1), 1); + } + "#, + ) + .file( + "tests/test_sub_one.rs", + r#" + extern crate foo; + use foo::*; + + #[test] + fn sub_one_test() { + assert_eq!(sub_one(1), 0); + } + "#, + ) + .build(); + p.cargo("test --no-fail-fast") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[RUNNING] tests/test_add_one.rs (target/debug/deps/test_add_one-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test test_add_one` +[RUNNING] tests/test_sub_one.rs (target/debug/deps/test_sub_one-[HASH][EXE]) +[DOCTEST] foo +[ERROR] 1 target failed: + `--test test_add_one` + +"#]]) + .with_stdout_data(str![[r#" +running 0 tests +test add_one_test ... ok +test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +test sub_one_test ... ok +test [..] ... ok +... +"#]].unordered()) + .run(); +} + +#[cargo_test] +fn test_multiple_packages() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies.d1] + path = "d1" + [dependencies.d2] + path = "d2" + + [lib] + name = "foo" + doctest = false + "#, + ) + .file("src/lib.rs", "") + .file( + "d1/Cargo.toml", + r#" + [package] + name = "d1" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "d1" + doctest = false + "#, + ) + .file("d1/src/lib.rs", "") + .file( + "d2/Cargo.toml", + r#" + [package] + name = "d2" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + name = "d2" + doctest = false + "#, + ) + .file("d2/src/lib.rs", ""); + let p = p.build(); + + p.cargo("test -p d1 -p d2") + .with_stderr_data(str![[r#" +... +[RUNNING] unittests src/lib.rs (target/debug/deps/d1-[HASH][EXE]) +[RUNNING] unittests src/lib.rs (target/debug/deps/d2-[HASH][EXE]) +... +"#]]) + .with_stdout_data( + str![[r#" +running 0 tests +running 0 tests +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn bin_does_not_rebuild_tests() { + let p = project() + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .file("tests/foo.rs", ""); + let p = p.build(); + + p.cargo("test -v").run(); + + sleep_ms(1000); + fs::write(p.root().join("src/main.rs"), "fn main() { 3; }").unwrap(); + + p.cargo("test -v --no-run") + .with_stderr_data(str![[r#" +[DIRTY] foo v0.0.1 ([ROOT]/foo): the file `src/main.rs` has changed ([..]) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..] src/main.rs [..]` +[RUNNING] `rustc [..] src/main.rs [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn selective_test_wonky_profile() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.release] + opt-level = 2 + + [dependencies] + a = { path = "a" } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", ""); + let p = p.build(); + + p.cargo("test -v --no-run --release -p foo -p a").run(); +} + +#[cargo_test] +fn selective_test_optional_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a", optional = true } + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", ""); + let p = p.build(); + + p.cargo("test -v --no-run --features a -p a") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[COMPILING] a v0.0.1 ([ROOT]/foo/a) +[RUNNING] `rustc [..] a/src/lib.rs [..]` +[RUNNING] `rustc [..] a/src/lib.rs [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[EXECUTABLE] `[ROOT]/foo/target/debug/deps/a-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn only_test_docs() { + let p = project() + .file( + "src/lib.rs", + r#" + #[test] + fn foo() { + let a: u32 = "hello"; + } + + /// ``` + /// foo::bar(); + /// println!("ok"); + /// ``` + pub fn bar() { + } + "#, + ) + .file("tests/foo.rs", "this is not rust"); + let p = p.build(); + + p.cargo("test --doc") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[DOCTEST] foo + +"#]]) + .with_stdout_data(str![[r#" +... +test [..] ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn doctest_with_library_paths() { + let p = project(); + // Only link search directories within the target output directory are + // propagated through to dylib_path_envvar() (see #3366). + let dir1 = p.target_debug_dir().join("foo\\backslash"); + let dir2 = p.target_debug_dir().join("dir=containing=equal=signs"); + + let p = p + .file("Cargo.toml", &basic_manifest("foo", "0.0.0")) + .file( + "build.rs", + &format!( + r##" + fn main() {{ + println!(r#"cargo::rustc-link-search=native={}"#); + println!(r#"cargo::rustc-link-search={}"#); + }} + "##, + dir1.display(), + dir2.display() + ), + ) + .file( + "src/lib.rs", + &format!( + r##" + /// ``` + /// foo::assert_search_path(); + /// ``` + pub fn assert_search_path() {{ + let search_path = std::env::var_os("{}").unwrap(); + let paths = std::env::split_paths(&search_path).collect::>(); + assert!(paths.contains(&r#"{}"#.into())); + assert!(paths.contains(&r#"{}"#.into())); + }} + "##, + dylib_path_envvar(), + dir1.display(), + dir2.display() + ), + ) + .build(); + + p.cargo("test --doc").run(); +} + +#[cargo_test] +fn test_panic_abort_with_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar" } + + [profile.dev] + panic = 'abort' + "#, + ) + .file( + "src/lib.rs", + r#" + extern crate bar; + + #[test] + fn foo() {} + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.0.1")) + .file("bar/src/lib.rs", "") + .build(); + p.cargo("test -v").run(); +} + +#[cargo_test] +fn cfg_test_even_with_no_harness() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [lib] + harness = false + doctest = false + "#, + ) + .file( + "src/lib.rs", + r#"#[cfg(test)] fn main() { println!("hello!"); }"#, + ) + .build(); + p.cargo("test -v") + .with_stdout_data(str![[r#" +hello! + +"#]]) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn panic_abort_multiple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + + [profile.release] + panic = 'abort' + "#, + ) + .file( + "src/lib.rs", + "#[allow(unused_extern_crates)] extern crate a;", + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + p.cargo("test --release -v -p foo -p a").run(); +} + +#[cargo_test] +fn pass_correct_cfgs_flags_to_rustdoc() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["feature_a/default"] + nightly = ["feature_a/nightly"] + + [dependencies.feature_a] + path = "libs/feature_a" + default-features = false + "#, + ) + .file( + "src/lib.rs", + r#" + #[cfg(test)] + mod tests { + #[test] + fn it_works() { + assert!(true); + } + } + "#, + ) + .file( + "libs/feature_a/Cargo.toml", + r#" + [package] + name = "feature_a" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + default = ["mock_serde_codegen"] + nightly = ["mock_serde_derive"] + + [dependencies] + mock_serde_derive = { path = "../mock_serde_derive", optional = true } + + [build-dependencies] + mock_serde_codegen = { path = "../mock_serde_codegen", optional = true } + "#, + ) + .file( + "libs/feature_a/src/lib.rs", + r#" + #[cfg(feature = "mock_serde_derive")] + const MSG: &'static str = "This is safe"; + + #[cfg(feature = "mock_serde_codegen")] + const MSG: &'static str = "This is risky"; + + pub fn get() -> &'static str { + MSG + } + "#, + ) + .file( + "libs/mock_serde_derive/Cargo.toml", + &basic_manifest("mock_serde_derive", "0.1.0"), + ) + .file("libs/mock_serde_derive/src/lib.rs", "") + .file( + "libs/mock_serde_codegen/Cargo.toml", + &basic_manifest("mock_serde_codegen", "0.1.0"), + ) + .file("libs/mock_serde_codegen/src/lib.rs", ""); + let p = p.build(); + + p.cargo("test --package feature_a --verbose") + .with_stderr_data(str![[r#" +... +[DOCTEST] feature_a +[RUNNING] `rustdoc [..]--test [..]mock_serde_codegen[..]` +... +"#]]) + .run(); + + p.cargo("test --verbose") + .with_stderr_data(str![[r#" +... +[DOCTEST] foo +[RUNNING] `rustdoc [..]--test [..]feature_a[..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_release_ignore_panic() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + + [profile.test] + panic = 'abort' + [profile.release] + panic = 'abort' + "#, + ) + .file( + "src/lib.rs", + "#[allow(unused_extern_crates)] extern crate a;", + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", ""); + let p = p.build(); + println!("test"); + p.cargo("test -v").run(); + println!("bench"); + p.cargo("bench -v").run(); +} + +#[cargo_test] +fn test_many_with_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + a = { path = "a" } + + [features] + foo = [] + + [workspace] + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.0.1")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("test -v -p a -p foo --features foo").run(); +} + +#[cargo_test] +fn test_all_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "#[test] fn foo_test() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] fn bar_test() {}") + .build(); + + p.cargo("test --workspace") + .with_stdout_data( + str![[r#" +test foo_test ... ok +test bar_test ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_all_exclude() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "#[test] pub fn baz() { assert!(false); }") + .build(); + + p.cargo("test --workspace --exclude baz") + .with_stdout_data(str![[r#" +... +running 1 test +test bar ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_all_exclude_not_found() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] pub fn bar() {}") + .build(); + + p.cargo("test --workspace --exclude baz") + .with_stderr_data(str![[r#" +... +[WARNING] excluded package(s) `baz` not found in workspace `[ROOT]/foo` +... +"#]]) + .with_stdout_data(str![[r#" +... +running 1 test +test bar ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_all_exclude_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "#[test] pub fn baz() { assert!(false); }") + .build(); + + p.cargo("test --workspace --exclude '*z'") + .with_stdout_data(str![[r#" +... +running 1 test +test bar ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_all_exclude_glob_not_found() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] pub fn bar() {}") + .build(); + + p.cargo("test --workspace --exclude '*z'") + .with_stderr_data(str![[r#" +... +[WARNING] excluded package pattern(s) `*z` not found in workspace `[ROOT]/foo` +... +"#]]) + .with_stdout_data(str![[r#" +... +running 1 test +test bar ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_all_exclude_broken_glob() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + p.cargo("test --workspace --exclude '[*z'") + .with_status(101) + .with_stderr_data(str![[r#" +... +[ERROR] cannot build glob pattern from `[*z` +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_all_virtual_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "#[test] fn a() {}") + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file("b/src/lib.rs", "#[test] fn b() {}") + .build(); + + p.cargo("test --workspace") + .with_stdout_data( + str![[r#" +running 1 test +test a ... ok +running 1 test +test b ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_virtual_manifest_all_implied() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "#[test] fn a() {}") + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file("b/src/lib.rs", "#[test] fn b() {}") + .build(); + + p.cargo("test") + .with_stdout_data( + str![[r#" +running 1 test +test a ... ok +running 1 test +test b ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn test_virtual_manifest_one_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "#[test] fn baz() { assert!(false); }") + .build(); + + p.cargo("test -p bar") + .with_stdout_contains("running 1 test\ntest bar ... ok") + .with_stdout_does_not_contain("running 1 test\ntest baz ... ok") + .run(); +} + +#[cargo_test] +fn test_virtual_manifest_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] fn bar() { assert!(false); }") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "#[test] fn baz() {}") + .build(); + + p.cargo("test -p '*z'") + .with_stdout_does_not_contain("running 1 test\ntest bar ... ok") + .with_stdout_contains("running 1 test\ntest baz ... ok") + .run(); +} + +#[cargo_test] +fn test_virtual_manifest_glob_not_found() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] fn bar() {}") + .build(); + + p.cargo("test -p bar -p '*z'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package pattern(s) `*z` not found in workspace `[ROOT]/foo` +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_virtual_manifest_broken_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "#[test] fn bar() {}") + .build(); + + p.cargo("test -p '[*z'") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot build glob pattern from `[*z` +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_all_member_dependency_same_name() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dependencies] + a = "0.1.0" + "#, + ) + .file("a/src/lib.rs", "#[test] fn a() {}") + .build(); + + Package::new("a", "0.1.0").publish(); + + p.cargo("test --workspace") + .with_stdout_data(str![[r#" +... +test a ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn doctest_only_with_dev_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dev-dependencies] + b = { path = "b" } + "#, + ) + .file( + "src/lib.rs", + r#" + /// ``` + /// extern crate b; + /// + /// b::b(); + /// ``` + pub fn a() {} + "#, + ) + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file("b/src/lib.rs", "pub fn b() {}") + .build(); + + p.cargo("test --doc -v").run(); +} + +#[cargo_test] +fn test_many_targets() { + let p = project() + .file( + "src/bin/a.rs", + r#" + fn main() {} + #[test] fn bin_a() {} + "#, + ) + .file( + "src/bin/b.rs", + r#" + fn main() {} + #[test] fn bin_b() {} + "#, + ) + .file( + "src/bin/c.rs", + r#" + fn main() {} + #[test] fn bin_c() { panic!(); } + "#, + ) + .file( + "examples/a.rs", + r#" + fn main() {} + #[test] fn example_a() {} + "#, + ) + .file( + "examples/b.rs", + r#" + fn main() {} + #[test] fn example_b() {} + "#, + ) + .file("examples/c.rs", "#[test] fn example_c() { panic!(); }") + .file("tests/a.rs", "#[test] fn test_a() {}") + .file("tests/b.rs", "#[test] fn test_b() {}") + .file("tests/c.rs", "does not compile") + .build(); + + p.cargo("test --verbose --bin a --bin b --example a --example b --test a --test b") + .with_stdout_data( + str![[r#" +test bin_a ... ok +test bin_b ... ok +test test_a ... ok +test test_b ... ok +... +"#]] + .unordered(), + ) + .with_stderr_data( + str![[r#" +[RUNNING] `rustc --crate-name a --edition=2015 examples/a.rs [..]` +[RUNNING] `rustc --crate-name b --edition=2015 examples/b.rs [..]` +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn doctest_and_registry() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + [dependencies] + b = { path = "b" } + c = { path = "c" } + + [workspace] + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file( + "b/src/lib.rs", + " + /// ``` + /// b::foo(); + /// ``` + pub fn foo() {} + ", + ) + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.1.0" + edition = "2015" + + [dependencies] + b = "0.1" + "#, + ) + .file("c/src/lib.rs", "") + .build(); + + Package::new("b", "0.1.0").publish(); + + p.cargo("test --workspace -v").run(); +} + +#[cargo_test] +fn cargo_test_env() { + let rustc_host = rustc_host(); + let src = format!( + r#" + #![crate_type = "rlib"] + + #[test] + fn env_test() {{ + use std::env; + eprintln!("{{}}", env::var("{}").unwrap()); + }} + "#, + cargo::CARGO_ENV + ); + + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", &src) + .build(); + + let cargo = format!( + "{}[EXE]", + cargo_exe() + .canonicalize() + .unwrap() + .with_extension("") + .to_str() + .unwrap() + .replace(rustc_host, "[HOST_TARGET]") + ); + p.cargo("test --lib -- --nocapture") + .with_stderr_contains(cargo) + .with_stdout_data(str![[r#" +... +test env_test ... ok +... +"#]]) + .run(); + + // Check that `cargo test` propagates the environment's $CARGO + let rustc = cargo_util::paths::resolve_executable("rustc".as_ref()) + .unwrap() + .canonicalize() + .unwrap(); + let stderr_rustc = format!( + "{}[EXE]", + rustc + .with_extension("") + .to_str() + .unwrap() + .replace(rustc_host, "[HOST_TARGET]") + ); + p.cargo("test --lib -- --nocapture") + // we use rustc since $CARGO is only used if it points to a path that exists + .env(cargo::CARGO_ENV, rustc) + .with_stderr_contains(stderr_rustc) + .with_stdout_data(str![[r#" +... +test env_test ... ok +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_order() { + let p = project() + .file("src/lib.rs", "#[test] fn test_lib() {}") + .file("tests/a.rs", "#[test] fn test_a() {}") + .file("tests/z.rs", "#[test] fn test_z() {}") + .build(); + + p.cargo("test --workspace") + .with_stdout_data(str![[r#" + +running 1 test +test test_lib ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test_a ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test test_z ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .run(); +} + +#[cargo_test] +fn cyclic_dev() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dev-dependencies] + foo = { path = "." } + "#, + ) + .file("src/lib.rs", "#[test] fn test_lib() {}") + .file("tests/foo.rs", "extern crate foo;") + .build(); + + p.cargo("test --workspace").run(); +} + +#[cargo_test] +fn cyclical_dep_with_missing_feature() { + // Checks for error handling when a cyclical dev-dependency specify a + // feature that doesn't exist. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dev-dependencies] + foo = { path = ".", features = ["missing"] } + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to select a version for `foo`. + ... required by package `foo v0.1.0 ([ROOT]/foo)` +versions that meet the requirements `*` are: 0.1.0 + +the package `foo` depends on `foo`, with features: `missing` but `foo` does not have these features. + + +failed to select a version for `foo` which could resolve this conflict + +"#]]) + .run(); +} + +#[cargo_test] +fn publish_a_crate_without_tests() { + Package::new("testless", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "testless" + version = "0.1.0" + edition = "2015" + exclude = ["tests/*"] + + [[test]] + name = "a_test" + "#, + ) + .file("src/lib.rs", "") + // In real life, the package will have a test, + // which would be excluded from .crate file by the + // `exclude` field. Our test harness does not honor + // exclude though, so let's just not add the file! + // .file("tests/a_test.rs", "") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + testless = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("test").run(); + p.cargo("test --package testless").run(); +} + +#[cargo_test] +fn find_dependency_of_proc_macro_dependency_with_target() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["root", "proc_macro_dep"] + "#, + ) + .file( + "root/Cargo.toml", + r#" + [package] + name = "root" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + proc_macro_dep = { path = "../proc_macro_dep" } + "#, + ) + .file( + "root/src/lib.rs", + r#" + #[macro_use] + extern crate proc_macro_dep; + + #[derive(Noop)] + pub struct X; + "#, + ) + .file( + "proc_macro_dep/Cargo.toml", + r#" + [package] + name = "proc_macro_dep" + version = "0.1.0" + edition = "2015" + authors = [] + + [lib] + proc-macro = true + + [dependencies] + baz = "^0.1" + "#, + ) + .file( + "proc_macro_dep/src/lib.rs", + r#" + extern crate baz; + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Noop)] + pub fn noop(_input: TokenStream) -> TokenStream { + "".parse().unwrap() + } + "#, + ) + .build(); + Package::new("bar", "0.1.0").publish(); + Package::new("baz", "0.1.0") + .dep("bar", "0.1") + .file("src/lib.rs", "extern crate bar;") + .publish(); + p.cargo("test --workspace --target").arg(rustc_host()).run(); +} + +#[cargo_test] +fn test_hint_not_masked_by_doctest() { + let p = project() + .file( + "src/lib.rs", + r#" + /// ``` + /// assert_eq!(1, 1); + /// ``` + pub fn this_works() {} + "#, + ) + .file( + "tests/integ.rs", + r#" + #[test] + fn this_fails() { + panic!(); + } + "#, + ) + .build(); + p.cargo("test --no-fail-fast") + .with_status(101) + .with_stdout_data( + str![[r#" +test this_fails ... FAILED +test [..]this_works (line [..]) ... ok +... +"#]] + .unordered(), + ) + .with_stderr_data(str![[r#" +... +[ERROR] test failed, to rerun pass `--test integ` +... +"#]]) + .run(); +} + +#[cargo_test] +fn test_hint_workspace_virtual() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b", "c"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "#[test] fn t1() {}") + .file("b/Cargo.toml", &basic_manifest("b", "0.1.0")) + .file("b/src/lib.rs", "#[test] fn t1() {assert!(false)}") + .file("c/Cargo.toml", &basic_manifest("c", "0.1.0")) + .file( + "c/src/lib.rs", + r#" + /// ```rust + /// assert_eq!(1, 2); + /// ``` + pub fn foo() {} + "#, + ) + .file( + "c/src/main.rs", + r#" + fn main() {} + + #[test] + fn from_main() { assert_eq!(1, 2); } + "#, + ) + .file( + "c/tests/t1.rs", + r#" + #[test] + fn from_int_test() { assert_eq!(1, 2); } + "#, + ) + .file( + "c/examples/ex1.rs", + r#" + fn main() {} + + #[test] + fn from_example() { assert_eq!(1, 2); } + "#, + ) + // This does not use #[bench] since it is unstable. #[test] works just + // the same for our purpose of checking the hint. + .file( + "c/benches/b1.rs", + r#" + #[test] + fn from_bench() { assert_eq!(1, 2); } + "#, + ) + .build(); + + // This depends on Units being sorted so that `b` fails first. + p.cargo("test") + .with_stderr_data( + str![[r#" +[COMPILING] c v0.1.0 ([ROOT]/foo/c) +[COMPILING] a v0.1.0 ([ROOT]/foo/a) +[COMPILING] b v0.1.0 ([ROOT]/foo/b) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/a-[HASH][EXE]) +[RUNNING] unittests src/lib.rs (target/debug/deps/b-[HASH][EXE]) +[ERROR] test failed, to rerun pass `-p b --lib` + +"#]] + .unordered(), + ) + .with_status(101) + .run(); + p.cargo("test") + .cwd("b") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs ([ROOT]/foo/target/debug/deps/b-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--lib` + +"#]]) + .with_status(101) + .run(); + p.cargo("test --no-fail-fast") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/a-[HASH][EXE]) +[RUNNING] unittests src/lib.rs (target/debug/deps/b-[HASH][EXE]) +[ERROR] test failed, to rerun pass `-p b --lib` +[RUNNING] unittests src/lib.rs (target/debug/deps/c-[HASH][EXE]) +[RUNNING] unittests src/main.rs (target/debug/deps/c-[HASH][EXE]) +[ERROR] test failed, to rerun pass `-p c --bin c` +[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE]) +[ERROR] test failed, to rerun pass `-p c --test t1` +[DOCTEST] a +[DOCTEST] b +[DOCTEST] c +[ERROR] doctest failed, to rerun pass `-p c --doc` +[ERROR] 4 targets failed: + `-p b --lib` + `-p c --bin c` + `-p c --test t1` + `-p c --doc` + +"#]]) + .with_status(101) + .run(); + // Check others that are not in the default set. + p.cargo("test -p c --examples --benches --no-fail-fast") + .with_stderr_data(str![[r#" +[COMPILING] c v0.1.0 ([ROOT]/foo/c) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/c-[HASH][EXE]) +[RUNNING] unittests src/main.rs (target/debug/deps/c-[HASH][EXE]) +[ERROR] test failed, to rerun pass `-p c --bin c` +[RUNNING] benches/b1.rs (target/debug/deps/b1-[HASH][EXE]) +[ERROR] test failed, to rerun pass `-p c --bench b1` +[RUNNING] unittests examples/ex1.rs (target/debug/examples/ex1-[HASH][EXE]) +[ERROR] test failed, to rerun pass `-p c --example ex1` +[ERROR] 3 targets failed: + `-p c --bin c` + `-p c --bench b1` + `-p c --example ex1` + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn test_hint_workspace_nonvirtual() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["a"] + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", "#[test] fn t1() {assert!(false)}") + .build(); + + p.cargo("test --workspace") + .with_stderr_data(str![[r#" +... +[ERROR] test failed, to rerun pass `-p a --lib` +... +"#]]) + .with_status(101) + .run(); + p.cargo("test -p a") + .with_stderr_data(str![[r#" +... +[ERROR] test failed, to rerun pass `-p a --lib` +... +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn json_artifact_includes_test_flag() { + // Verify that the JSON artifact output includes `test` flag. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [profile.test] + opt-level = 1 + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("test --lib -v --no-run --message-format=json") + .with_stdout_data( + str![[r#" +[ + { + "executable": "[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]", + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn json_artifact_includes_executable_for_library_tests() { + let p = project() + .file("src/main.rs", "fn main() { }") + .file("src/lib.rs", r#"#[test] fn lib_test() {}"#) + .build(); + + p.cargo("test --lib -v --no-run --message-format=json") + .with_stdout_data( + str![[r#" +[ + { + "executable": "[ROOT]/foo/target/debug/deps/foo-[HASH][EXE]", + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn json_artifact_includes_executable_for_integration_tests() { + let p = project() + .file( + "tests/integration_test.rs", + r#"#[test] fn integration_test() {}"#, + ) + .build(); + + p.cargo("test -v --no-run --message-format=json --test integration_test") + .with_stdout_data( + str![[r#" +[ + { + "executable": "[ROOT]/foo/target/debug/deps/integration_test-[HASH][EXE]", + "features": [], + "filenames": "{...}", + "fresh": false, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "package_id": "path+[ROOTURL]/foo#0.0.1", + "profile": "{...}", + "reason": "compiler-artifact", + "target": { + "crate_types": [ + "bin" + ], + "doc": false, + "doctest": false, + "edition": "2015", + "kind": [ + "test" + ], + "name": "integration_test", + "src_path": "[ROOT]/foo/tests/integration_test.rs", + "test": true + } + }, + { + "reason": "build-finished", + "success": true + } +] +"#]] + .is_json() + .against_jsonlines(), + ) + .run(); +} + +#[cargo_test] +fn test_build_script_links() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + links = 'something' + + [lib] + test = false + "#, + ) + .file("build.rs", "fn main() {}") + .file("src/lib.rs", "") + .build(); + + p.cargo("test --no-run").run(); +} + +#[cargo_test] +fn doctest_skip_staticlib() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [lib] + crate-type = ["staticlib"] + "#, + ) + .file( + "src/lib.rs", + r#" + //! ``` + //! assert_eq!(1,2); + //! ``` + "#, + ) + .build(); + + p.cargo("test --doc") + .with_status(101) + .with_stderr_data(str![[r#" +[WARNING] doc tests are not supported for crate type(s) `staticlib` in package `foo` +[ERROR] no library targets found in package `foo` + +"#]]) + .run(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test] +fn can_not_mix_doc_tests_and_regular_tests() { + let p = project() + .file( + "src/lib.rs", + "\ +/// ``` +/// assert_eq!(1, 1) +/// ``` +pub fn foo() -> u8 { 1 } + +#[cfg(test)] mod tests { + #[test] fn it_works() { assert_eq!(2 + 2, 4); } +} +", + ) + .build(); + + p.cargo("test") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) +[DOCTEST] foo + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test tests::it_works ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +running 1 test +test src/lib.rs - foo (line 1) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + p.cargo("test --lib") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test tests::it_works ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .run(); + + // This has been modified to attempt to diagnose spurious errors on CI. + // For some reason, this is recompiling the lib when it shouldn't. If the + // root cause is ever found, the changes here should be reverted. + // See https://github.com/rust-lang/cargo/issues/6887 + p.cargo("test --doc -vv") + .with_stderr_does_not_contain("[COMPILING] foo [..]") + .with_stderr_data(str![[r#" +... +[DOCTEST] foo +... +"#]]) + .with_stdout_data(str![[r#" + +running 1 test +test src/lib.rs - foo (line 1) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s + + +"#]]) + .env("CARGO_LOG", "cargo=trace") + .run(); + + p.cargo("test --lib --doc") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Can't mix --doc with other target selecting options + +"#]]) + .run(); +} + +#[cargo_test] +fn can_not_no_run_doc_tests() { + let p = project() + .file( + "src/lib.rs", + r#" + /// ``` + /// let _x = 1 + "foo"; + /// ``` + pub fn foo() -> u8 { 1 } + "#, + ) + .build(); + + p.cargo("test --doc --no-run") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] Can't skip running doc tests with --no-run + +"#]]) + .run(); +} + +#[cargo_test] +fn test_all_targets_lib() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("test --all-targets") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] unittests src/lib.rs (target/debug/deps/foo-[HASH][EXE]) + +"#]]) + .run(); +} + +#[cargo_test] +fn test_dep_with_dev() { + Package::new("devdep", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + + [dev-dependencies] + devdep = "0.1" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("test -p bar") + .with_status(101) + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +[ERROR] package `bar` cannot be tested because it requires dev-dependencies and is not a member of the workspace + +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")] +fn cargo_test_doctest_xcompile_ignores() { + // -Zdoctest-xcompile also enables --enable-per-target-ignores which + // allows the ignore-TARGET syntax. + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/lib.rs", + r#" + ///```ignore-x86_64 + ///assert!(cfg!(not(target_arch = "x86_64"))); + ///``` + pub fn foo() -> u8 { + 4 + } + "#, + ) + .build(); + + p.cargo("build").run(); + #[cfg(not(target_arch = "x86_64"))] + p.cargo("test") + .with_stdout_data(str![[r#" +... +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .run(); + #[cfg(target_arch = "x86_64")] + p.cargo("test") + .with_status(101) + .with_stdout_data(str![[r#" +... +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]], + ) + .run(); + + #[cfg(not(target_arch = "x86_64"))] + p.cargo("test -Zdoctest-xcompile") + .masquerade_as_nightly_cargo(&["doctest-xcompile"]) + .with_stdout_data(str![[r#" +... +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .run(); + + #[cfg(target_arch = "x86_64")] + p.cargo("test -Zdoctest-xcompile") + .masquerade_as_nightly_cargo(&["doctest-xcompile"]) + .with_stdout_data(str![[r#" +... +test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")] +fn cargo_test_doctest_xcompile() { + if !cross_compile::can_run_on_host() { + return; + } + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/lib.rs", + r#" + + ///``` + ///assert!(1 == 1); + ///``` + pub fn foo() -> u8 { + 4 + } + "#, + ) + .build(); + + p.cargo("build").run(); + p.cargo(&format!("test --target {}", cross_compile::alternate())) + .with_stdout_data(str![[r#" +... +running 0 tests +... +"#]]) + .run(); + p.cargo(&format!( + "test --target {} -Zdoctest-xcompile", + cross_compile::alternate() + )) + .masquerade_as_nightly_cargo(&["doctest-xcompile"]) + .with_stdout_data(str![[r#" +... +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")] +fn cargo_test_doctest_xcompile_runner() { + if !cross_compile::can_run_on_host() { + return; + } + + let runner = project() + .file("Cargo.toml", &basic_bin_manifest("runner")) + .file( + "src/main.rs", + r#" + pub fn main() { + eprintln!("this is a runner"); + let args: Vec = std::env::args().collect(); + std::process::Command::new(&args[1]).spawn(); + } + "#, + ) + .build(); + + runner.cargo("build").run(); + assert!(runner.bin("runner").is_file()); + let runner_path = paths::root().join("runner"); + fs::copy(&runner.bin("runner"), &runner_path).unwrap(); + + let config = paths::root().join(".cargo/config.toml"); + + fs::create_dir_all(config.parent().unwrap()).unwrap(); + // Escape Windows backslashes for TOML config. + let runner_str = runner_path.to_str().unwrap().replace('\\', "\\\\"); + fs::write( + config, + format!( + r#" + [target.'cfg(target_arch = "{}")'] + runner = "{}" + "#, + cross_compile::alternate_arch(), + runner_str + ), + ) + .unwrap(); + + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/lib.rs", + &format!( + r#" + ///``` + ///assert!(cfg!(target_arch = "{}")); + ///``` + pub fn foo() -> u8 {{ + 4 + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + p.cargo("build").run(); + p.cargo(&format!("test --target {}", cross_compile::alternate())) + .with_stdout_data(str![[r#" +... +running 0 tests +... +"#]]) + .run(); + p.cargo(&format!( + "test --target {} -Zdoctest-xcompile", + cross_compile::alternate() + )) + .masquerade_as_nightly_cargo(&["doctest-xcompile"]) + .with_stdout_data(str![[r#" +... +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .with_stderr_data(str![[r#" +... +this is a runner +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zdoctest-xcompile is unstable")] +fn cargo_test_doctest_xcompile_no_runner() { + if !cross_compile::can_run_on_host() { + return; + } + + let p = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file( + "src/lib.rs", + &format!( + r#" + ///``` + ///assert!(cfg!(target_arch = "{}")); + ///``` + pub fn foo() -> u8 {{ + 4 + }} + "#, + cross_compile::alternate_arch() + ), + ) + .build(); + + p.cargo("build").run(); + p.cargo(&format!("test --target {}", cross_compile::alternate())) + .with_stdout_data(str![[r#" +... +running 0 tests +... +"#]]) + .run(); + p.cargo(&format!( + "test --target {} -Zdoctest-xcompile", + cross_compile::alternate() + )) + .masquerade_as_nightly_cargo(&["doctest-xcompile"]) + .with_stdout_data(str![[r#" +... +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in [ELAPSED]s +... +"#]]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zpanic-abort-tests in rustc is unstable")] +fn panic_abort_tests() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = "2015" + + [dependencies] + a = { path = 'a' } + + [profile.dev] + panic = 'abort' + [profile.test] + panic = 'abort' + "#, + ) + .file( + "src/lib.rs", + r#" + #[test] + fn foo() { + a::foo(); + } + "#, + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "pub fn foo() {}") + .build(); + + // This uses -j1 because of a race condition. Otherwise it will build the + // two copies of `foo` in parallel, and which one is first is random. If + // `--test` is first, then the first line with `[..]` will match, and the + // second line with `--test` will fail. + p.cargo("test -Z panic-abort-tests -v -j1") + .with_stderr_data( + str![[r#" +[RUNNING] `[..]--crate-name a [..]-C panic=abort[..]` +[RUNNING] `[..]--crate-name foo [..]-C panic=abort[..]` +[RUNNING] `[..]--crate-name foo [..]-C panic=abort[..]--test[..]` +... +"#]] + .unordered(), + ) + .masquerade_as_nightly_cargo(&["panic-abort-tests"]) + .run(); +} + +#[cargo_test] // Unlike with rustc, `rustdoc --test -Cpanic=abort` already works on stable +fn panic_abort_doc_tests() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = "2015" + + [profile.dev] + panic = 'abort' + "#, + ) + .file( + "src/lib.rs", + r#" + //! ```should_panic + //! panic!(); + //! ``` + "#, + ) + .build(); + + p.cargo("test --doc -Z panic-abort-tests -v") + .with_stderr_data( + str![[r#" +[RUNNING] `[..]rustc[..] --crate-name foo [..]-C panic=abort[..]` +[RUNNING] `[..]rustdoc[..] --crate-name foo [..]--test[..]-C panic=abort[..]` +... +"#]] + .unordered(), + ) + .masquerade_as_nightly_cargo(&["panic-abort-tests"]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zpanic-abort-tests in rustc is unstable")] +fn panic_abort_only_test() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = "2015" + + [dependencies] + a = { path = 'a' } + + [profile.test] + panic = 'abort' + "#, + ) + .file( + "src/lib.rs", + r#" + #[test] + fn foo() { + a::foo(); + } + "#, + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("test -Z panic-abort-tests -v") + .with_stderr_data(str![[r#" +[WARNING] `panic` setting is ignored for `test` profile +... +"#]]) + .masquerade_as_nightly_cargo(&["panic-abort-tests"]) + .run(); +} + +#[cargo_test(nightly, reason = "-Zpanic-abort-tests in rustc is unstable")] +fn panic_abort_test_profile_inherits() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = 'foo' + version = '0.1.0' + edition = "2015" + + [dependencies] + a = { path = 'a' } + + [profile.dev] + panic = 'abort' + "#, + ) + .file( + "src/lib.rs", + r#" + #[test] + fn foo() { + a::foo(); + } + "#, + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "pub fn foo() {}") + .build(); + + p.cargo("test -Z panic-abort-tests -v") + .masquerade_as_nightly_cargo(&["panic-abort-tests"]) + .with_status(0) + .run(); +} + +#[cargo_test] +fn bin_env_for_test() { + // Test for the `CARGO_BIN_EXE_` environment variables for tests. + // + // Note: The Unicode binary uses a `[[bin]]` definition because different + // filesystems normalize utf-8 in different ways. For example, HFS uses + // "gru\u{308}ßen" and APFS uses "gr\u{fc}ßen". Defining it in TOML forces + // one form to be used. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [[bin]] + name = 'grüßen' + path = 'src/bin/grussen.rs' + "#, + ) + .file("src/bin/foo.rs", "fn main() {}") + .file("src/bin/with-dash.rs", "fn main() {}") + .file("src/bin/grussen.rs", "fn main() {}") + .build(); + + let bin_path = |name| p.bin(name).to_string_lossy().replace("\\", "\\\\"); + p.change_file( + "tests/check_env.rs", + &r#" + #[test] + fn run_bins() { + assert_eq!(env!("CARGO_BIN_EXE_foo"), ""); + assert_eq!(env!("CARGO_BIN_EXE_with-dash"), ""); + assert_eq!(env!("CARGO_BIN_EXE_grüßen"), ""); + } + "# + .replace("", &bin_path("foo")) + .replace("", &bin_path("with-dash")) + .replace("", &bin_path("grüßen")), + ); + + p.cargo("test --test check_env").run(); + p.cargo("check --test check_env").run(); +} + +#[cargo_test] +fn test_workspaces_cwd() { + // This tests that all the different test types are executed from the + // crate directory (manifest_dir), and not from the workspace root. + + let make_lib_file = |expected| { + format!( + r#" + //! ``` + //! assert_eq!("{expected}", std::fs::read_to_string("file.txt").unwrap()); + //! assert_eq!("{expected}", include_str!("../file.txt")); + //! assert_eq!( + //! std::path::PathBuf::from(std::env!("CARGO_MANIFEST_DIR")), + //! std::env::current_dir().unwrap(), + //! ); + //! ``` + + #[test] + fn test_unit_{expected}_cwd() {{ + assert_eq!("{expected}", std::fs::read_to_string("file.txt").unwrap()); + assert_eq!("{expected}", include_str!("../file.txt")); + assert_eq!( + std::path::PathBuf::from(std::env!("CARGO_MANIFEST_DIR")), + std::env::current_dir().unwrap(), + ); + }} + "#, + expected = expected + ) + }; + let make_test_file = |expected| { + format!( + r#" + #[test] + fn test_integration_{expected}_cwd() {{ + assert_eq!("{expected}", std::fs::read_to_string("file.txt").unwrap()); + assert_eq!("{expected}", include_str!("../file.txt")); + assert_eq!( + std::path::PathBuf::from(std::env!("CARGO_MANIFEST_DIR")), + std::env::current_dir().unwrap(), + ); + }} + "#, + expected = expected + ) + }; + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "root-crate" + version = "0.0.0" + + [workspace] + members = [".", "nested-crate", "very/deeply/nested/deep-crate"] + "#, + ) + .file("file.txt", "root") + .file("src/lib.rs", &make_lib_file("root")) + .file("tests/integration.rs", &make_test_file("root")) + .file( + "nested-crate/Cargo.toml", + r#" + [package] + name = "nested-crate" + version = "0.0.0" + "#, + ) + .file("nested-crate/file.txt", "nested") + .file("nested-crate/src/lib.rs", &make_lib_file("nested")) + .file( + "nested-crate/tests/integration.rs", + &make_test_file("nested"), + ) + .file( + "very/deeply/nested/deep-crate/Cargo.toml", + r#" + [package] + name = "deep-crate" + version = "0.0.0" + "#, + ) + .file("very/deeply/nested/deep-crate/file.txt", "deep") + .file( + "very/deeply/nested/deep-crate/src/lib.rs", + &make_lib_file("deep"), + ) + .file( + "very/deeply/nested/deep-crate/tests/integration.rs", + &make_test_file("deep"), + ) + .build(); + + p.cargo("test --workspace --all") + .with_stderr_data( + str![[r#" +[DOCTEST] root_crate +[DOCTEST] nested_crate +[DOCTEST] deep_crate +... +"#]] + .unordered(), + ) + .with_stdout_data( + str![[r#" +test test_unit_root_cwd ... ok +test test_unit_nested_cwd ... ok +test test_unit_deep_cwd ... ok +test test_integration_root_cwd ... ok +test test_integration_nested_cwd ... ok +test test_integration_deep_cwd ... ok +... +"#]] + .unordered(), + ) + .run(); + + p.cargo("test -p root-crate --all") + .with_stderr_data(str![[r#" +... +[DOCTEST] root_crate +... +"#]]) + .with_stdout_data( + str![[r#" +test test_unit_root_cwd ... ok +test test_integration_root_cwd ... ok +... +"#]] + .unordered(), + ) + .run(); + + p.cargo("test -p nested-crate --all") + .with_stderr_data(str![[r#" +... +[DOCTEST] nested_crate +... +"#]]) + .with_stdout_data( + str![[r#" +test test_unit_nested_cwd ... ok +test test_integration_nested_cwd ... ok +... +"#]] + .unordered(), + ) + .run(); + + p.cargo("test -p deep-crate --all") + .with_stderr_data(str![[r#" +... +[DOCTEST] deep_crate +... +"#]]) + .with_stdout_data( + str![[r#" +test test_unit_deep_cwd ... ok +test test_integration_deep_cwd ... ok +... +"#]] + .unordered(), + ) + .run(); + + p.cargo("test --all") + .cwd("nested-crate") + .with_stderr_data(str![[r#" +... +[DOCTEST] nested_crate +... +"#]]) + .with_stdout_data( + str![[r#" +test test_unit_nested_cwd ... ok +test test_integration_nested_cwd ... ok +... +"#]] + .unordered(), + ) + .run(); + + p.cargo("test --all") + .cwd("very/deeply/nested/deep-crate") + .with_stderr_data(str![[r#" +... +[DOCTEST] deep_crate +... +"#]]) + .with_stdout_data( + str![[r#" +test test_unit_deep_cwd ... ok +test test_integration_deep_cwd ... ok +... +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn execution_error() { + // Checks the behavior when a test fails to launch. + let p = project() + .file( + "tests/t1.rs", + r#" + #[test] + fn foo() {} + "#, + ) + .build(); + let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env()); + p.cargo("test") + .env(&key, "does_not_exist") + // The actual error is usually "no such file", but on Windows it has a + // custom message. Since matching against the error string produced by + // Rust is not very reliable, this just uses `[..]`. + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test t1` + +Caused by: + could not execute process `does_not_exist [ROOT]/foo/target/debug/deps/t1-[HASH][EXE]` (never executed) + +Caused by: + [NOT_FOUND] + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn nonzero_exit_status() { + // Tests for nonzero exit codes from tests. + let p = project() + .file( + "tests/t1.rs", + r#" + #[test] + fn t() { panic!("this is a normal error") } + "#, + ) + .file( + "tests/t2.rs", + r#" + #[test] + fn t() { std::process::exit(4) } + "#, + ) + .build(); + + p.cargo("test --test t1") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test t1` + +"#]]) + .with_stdout_data(str![[r#" +... +this is a normal error +... +"#]]) + .with_status(101) + .run(); + + p.cargo("test --test t2") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/t2.rs (target/debug/deps/t2-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test t2` + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE]` ([EXIT_STATUS]: 4) +[NOTE] test exited abnormally; to see the full output pass --nocapture to the harness. + +"#]]) + .with_status(4) + .run(); + + p.cargo("test --test t2 -- --nocapture") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/t2.rs (target/debug/deps/t2-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test t2` + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE] --nocapture` ([EXIT_STATUS]: 4) + +"#]]) + .with_status(4) + .run(); + + // no-fail-fast always uses 101 + p.cargo("test --no-fail-fast") + .with_stderr_data(str![[r#" +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] tests/t1.rs (target/debug/deps/t1-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test t1` +[RUNNING] tests/t2.rs (target/debug/deps/t2-[HASH][EXE]) +[ERROR] test failed, to rerun pass `--test t2` + +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE]` ([EXIT_STATUS]: 4) +[NOTE] test exited abnormally; to see the full output pass --nocapture to the harness. +[ERROR] 2 targets failed: + `--test t1` + `--test t2` + +"#]]) + .with_status(101) + .run(); + + p.cargo("test --no-fail-fast -- --nocapture") + .with_stderr_does_not_contain( + "test exited abnormally; to see the full output pass --nocapture to the harness.", + ) + .with_stderr_data(str![[r#" +[..]thread [..]panicked [..] tests/t1.rs[..] +[NOTE] run with `RUST_BACKTRACE=1` environment variable to display a backtrace +Caused by: + process didn't exit successfully: `[ROOT]/foo/target/debug/deps/t2-[HASH][EXE] --nocapture` ([EXIT_STATUS]: 4) +... +"#]].unordered()) + .with_status(101) + .run(); +} + +#[cargo_test] +fn cargo_test_print_env_verbose() { + let p = project() + .file("Cargo.toml", &basic_manifest("foo", "0.0.1")) + .file("src/lib.rs", "") + .build(); + + p.cargo("test -vv").with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc --crate-name foo[..]` +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustc --crate-name foo[..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] [ROOT]/foo/target/debug/deps/foo-[HASH][EXE]` +[DOCTEST] foo +[RUNNING] `[..]CARGO_MANIFEST_DIR=[ROOT]/foo[..] rustdoc --edition=2015 --crate-type lib --color auto --crate-name foo[..]` + +"#]]).run(); +} + +#[cargo_test] +fn cargo_test_set_out_dir_env_var() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + "#, + ) + .file( + "src/lib.rs", + r#" + pub fn add(left: u64, right: u64) -> u64 { + left + right + } + "#, + ) + .file( + "build.rs", + r#" + fn main() {} + "#, + ) + .file( + "tests/case.rs", + r#" + #[cfg(test)] + pub mod tests { + #[test] + fn test_add() { + assert!(std::env::var("OUT_DIR").is_ok()); + assert_eq!(foo::add(2, 5), 7); + } + } + "#, + ) + .build(); + + p.cargo("test").run(); + p.cargo("test --package foo --test case -- tests::test_add --exact --nocapture") + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/timings.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/timings.rs new file mode 100644 index 000000000..cea0e2887 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/timings.rs @@ -0,0 +1,56 @@ +//! Tests for --timings. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +#[cargo_test] +fn timings_works() { + Package::new("dep", "0.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = "0.1" + "#, + ) + .file("src/lib.rs", "") + .file("src/main.rs", "fn main() {}") + .file("tests/t1.rs", "") + .file("examples/ex1.rs", "fn main() {}") + .build(); + + p.cargo("build --all-targets --timings") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep v0.1.0 (registry `dummy-registry`) +[COMPILING] dep v0.1.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) + Timing report saved to [ROOT]/foo/target/cargo-timings/cargo-timing-[..].html +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("clean").run(); + + p.cargo("test --timings").run(); + + p.cargo("clean").run(); + + p.cargo("check --timings").run(); + + p.cargo("clean").run(); + + p.cargo("doc --timings").run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tool_paths.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tool_paths.rs new file mode 100644 index 000000000..b733d6f9b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tool_paths.rs @@ -0,0 +1,487 @@ +//! Tests for configuration values that point to programs. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_lib_manifest, project, rustc_host, rustc_host_env, str}; + +#[cargo_test] +fn pathless_tools() { + let target = rustc_host(); + + let foo = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + linker = "nonexistent-linker" + "#, + target + ), + ) + .build(); + + foo.cargo("build --verbose") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .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.toml", + r#" + [target.'cfg(not(target_os = "none"))'] + linker = "nonexistent-linker" + "#, + ) + .build(); + + foo.cargo("build --verbose") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .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.toml", + &format!( + r#" + [target.'cfg(not(target_os = "none"))'] + linker = "ignored-linker" + [target.{}] + linker = "nonexistent-linker" + "#, + target + ), + ) + .build(); + + foo.cargo("build --verbose") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .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.toml", + 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_data(str![[r#" +[ERROR] several matching instances of `target.'cfg(..)'.linker` in configurations +first match `cfg(not(target_arch = "avr"))` located in [ROOT]/foo/.cargo/config.toml +second match `cfg(not(target_os = "none"))` located in [ROOT]/foo/.cargo/config.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn absolute_tools() { + let target = rustc_host(); + + // Escaped as they appear within a TOML config file + let linker = if cfg!(windows) { + r#"C:\\bogus\\nonexistent-linker"# + } else { + r#"/bogus/nonexistent-linker"# + }; + + let foo = project() + .file("Cargo.toml", &basic_lib_manifest("foo")) + .file("src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{target}] + linker = "{linker}" + "#, + target = target, + linker = linker + ), + ) + .build(); + + foo.cargo("build --verbose") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.5.0 ([ROOT]/foo) +[RUNNING] `rustc [..]-C linker=[..]/bogus/nonexistent-linker [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn relative_tools() { + let target = rustc_host(); + + // Escaped as they appear within a TOML config file + let linker = if cfg!(windows) { + r#".\\tools\\nonexistent-linker"# + } else { + r#"./tools/nonexistent-linker"# + }; + + // Funky directory structure to test that relative tool paths are made absolute + // by reference to the `.cargo/..` directory and not to (for example) the CWD. + let p = project() + .no_manifest() + .file("bar/Cargo.toml", &basic_lib_manifest("bar")) + .file("bar/src/lib.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{target}] + linker = "{linker}" + "#, + target = target, + linker = linker + ), + ) + .build(); + + p.cargo("build --verbose") + .cwd("bar") + .with_stderr_data(str![[r#" +[COMPILING] bar v0.5.0 ([ROOT]/foo/bar) +[RUNNING] `rustc [..]-C linker=[ROOT]/foo/./tools/nonexistent-linker [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_runner() { + let target = rustc_host(); + + let p = project() + .file("src/main.rs", "fn main() {}") + .file("tests/test.rs", "") + .file("benches/bench.rs", "") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + runner = "nonexistent-runner -r" + "#, + target + ), + ) + .build(); + + p.cargo("run -- --param") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param` +... +"#]]) + .run(); + + p.cargo("test --test test --verbose -- --param") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[FINISHED] `test` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `nonexistent-runner -r [ROOT]/foo/target/debug/deps/test-[HASH][EXE] --param` +... +"#]]) + .run(); + + p.cargo("bench --bench bench --verbose -- --param") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]` +[RUNNING] `rustc [..]` +[FINISHED] `bench` profile [optimized] target(s) in [ELAPSED]s +[RUNNING] `nonexistent-runner -r [ROOT]/foo/target/release/deps/bench-[HASH][EXE] --param --bench` +... +"#]]) + .run(); +} + +// can set a custom runner via `target.'cfg(..)'.runner` +#[cargo_test] +fn custom_runner_cfg() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [target.'cfg(not(target_os = "none"))'] + runner = "nonexistent-runner -r" + "#, + ) + .build(); + + p.cargo("run -- --param") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param` +... +"#]]) + .run(); +} + +// custom runner set via `target.$triple.runner` have precedence over `target.'cfg(..)'.runner` +#[cargo_test] +fn custom_runner_cfg_precedence() { + let target = rustc_host(); + + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.'cfg(not(target_os = "none"))'] + runner = "ignored-runner" + + [target.{}] + runner = "nonexistent-runner -r" + "#, + target + ), + ) + .build(); + + p.cargo("run -- --param") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `nonexistent-runner -r target/debug/foo[EXE] --param` +... +"#]]) + .run(); +} + +#[cargo_test] +fn custom_runner_cfg_collision() { + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + r#" + [target.'cfg(not(target_arch = "avr"))'] + runner = "true" + + [target.'cfg(not(target_os = "none"))'] + runner = "false" + "#, + ) + .build(); + + p.cargo("run -- --param") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] several matching instances of `target.'cfg(..)'.runner` in configurations +first match `cfg(not(target_arch = "avr"))` located in [ROOT]/foo/.cargo/config.toml +second match `cfg(not(target_os = "none"))` located in [ROOT]/foo/.cargo/config.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_runner_env() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env()); + + p.cargo("run") + .env(&key, "nonexistent-runner --foo") + .with_status(101) + // FIXME: Update "Caused by" error message once rust/pull/87704 is merged. + // On Windows, changing to a custom executable resolver has changed the + // error messages. + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `nonexistent-runner --foo target/debug/foo[EXE]` +[ERROR] could not execute process `nonexistent-runner --foo target/debug/foo[EXE]` (never executed) + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_runner_env_overrides_config() { + let target = rustc_host(); + let p = project() + .file("src/main.rs", "fn main() {}") + .file( + ".cargo/config.toml", + &format!( + r#" + [target.{}] + runner = "should-not-run -r" + "#, + target + ), + ) + .build(); + + let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env()); + + p.cargo("run") + .env(&key, "should-run --foo") + .with_status(101) + .with_stderr_data(str![[r#" +... +[RUNNING] `should-run --foo target/debug/foo[EXE]` +... +"#]]) + .run(); +} + +#[cargo_test] +#[cfg(unix)] // Assumes `true` is in PATH. +fn custom_runner_env_true() { + // Check for a bug where "true" was interpreted as a boolean instead of + // the executable. + let p = project().file("src/main.rs", "fn main() {}").build(); + + let key = format!("CARGO_TARGET_{}_RUNNER", rustc_host_env()); + + p.cargo("run") + .env(&key, "true") + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `true target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn custom_linker_env() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + let key = format!("CARGO_TARGET_{}_LINKER", rustc_host_env()); + + p.cargo("build -v") + .env(&key, "nonexistent-linker") + .with_status(101) + .with_stderr_data(str![[r#" +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc [..]-C linker=nonexistent-linker [..]` +... +"#]]) + .run(); +} + +#[cargo_test] +fn target_in_environment_contains_lower_case() { + let p = project().file("src/main.rs", "fn main() {}").build(); + + let target = rustc_host(); + let env_key = format!( + "CARGO_TARGET_{}_LINKER", + target.to_lowercase().replace('-', "_") + ); + + p.cargo("build -v --target") + .arg(target) + .env(&env_key, "nonexistent-linker") + .with_stderr_data(format!("\ +[WARNING] environment variables are expected to use uppercase letters and underscores, the variable `{env_key}` will be ignored and have no effect +[WARNING] environment variables are expected to use uppercase letters and underscores, the variable `{env_key}` will be ignored and have no effect +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `rustc --crate-name foo --edition=2015 src/main.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +" + )) + .run(); +} + +#[cargo_test] +fn cfg_ignored_fields() { + // Test for some ignored fields in [target.'cfg()'] tables. + let p = project() + .file( + ".cargo/config.toml", + r#" + # Try some empty tables. + [target.'cfg(not(foo))'] + [target.'cfg(not(bar))'.somelib] + + # A bunch of unused fields. + [target.'cfg(not(target_os = "none"))'] + linker = 'false' + ar = 'false' + foo = {rustc-flags = "-l foo"} + invalid = 1 + runner = 'false' + rustflags = '' + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[WARNING] unused key `somelib` in [target] config table `cfg(not(bar))` +[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"))` +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree.rs new file mode 100644 index 000000000..632af27b7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree.rs @@ -0,0 +1,2187 @@ +//! Tests for the `cargo tree` command. + +use cargo_test_support::cross_compile::{self, alternate}; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::str; +use cargo_test_support::{basic_manifest, git, project, rustc_host, Project}; + +use super::features2::switch_to_resolver_2; + +fn make_simple_proj() -> Project { + Package::new("c", "1.0.0").publish(); + Package::new("b", "1.0.0").dep("c", "1.0").publish(); + Package::new("a", "1.0.0").dep("b", "1.0").publish(); + Package::new("bdep", "1.0.0").dep("b", "1.0").publish(); + Package::new("devdep", "1.0.0").dep("b", "1.0.0").publish(); + + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = "1.0" + c = "1.0" + + [build-dependencies] + bdep = "1.0" + + [dev-dependencies] + devdep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build() +} + +#[cargo_test] +fn simple() { + // A simple test with a few different dependencies. + let p = make_simple_proj(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── a v1.0.0 +│ └── b v1.0.0 +│ └── c v1.0.0 +└── c v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── b v1.0.0 (*) +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) + +"#]]) + .run(); + + p.cargo("tree -p bdep") + .with_stdout_data(str![[r#" +bdep v1.0.0 +└── b v1.0.0 + └── c v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_workspace() { + // Multiple packages in a virtual workspace. + Package::new("somedep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "baz", "c"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "1.0.0")) + .file("a/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + + [dependencies] + c = { path = "../c" } + somedep = "1.0" + "#, + ) + .file("baz/src/lib.rs", "") + .file("c/Cargo.toml", &basic_manifest("c", "1.0.0")) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +a v1.0.0 ([ROOT]/foo/a) + +baz v0.1.0 ([ROOT]/foo/baz) +├── c v1.0.0 ([ROOT]/foo/c) +└── somedep v1.0.0 + +c v1.0.0 ([ROOT]/foo/c) + +"#]]) + .run(); + + p.cargo("tree -p a") + .with_stdout_data(str![[r#" +a v1.0.0 ([ROOT]/foo/a) + +"#]]) + .run(); + + p.cargo("tree") + .cwd("baz") + .with_stdout_data(str![[r#" +baz v0.1.0 ([ROOT]/foo/baz) +├── c v1.0.0 ([ROOT]/foo/c) +└── somedep v1.0.0 + +"#]]) + .run(); + + // exclude baz + p.cargo("tree --workspace --exclude baz") + .with_stdout_data(str![[r#" +a v1.0.0 ([ROOT]/foo/a) + +c v1.0.0 ([ROOT]/foo/c) + +"#]]) + .run(); + + // exclude glob '*z' + p.cargo("tree --workspace --exclude '*z'") + .with_stdout_data(str![[r#" +a v1.0.0 ([ROOT]/foo/a) + +c v1.0.0 ([ROOT]/foo/c) + +"#]]) + .run(); + + // include glob '*z' + p.cargo("tree -p '*z'") + .with_stdout_data(str![[r#" +baz v0.1.0 ([ROOT]/foo/baz) +├── c v1.0.0 ([ROOT]/foo/c) +└── somedep v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn dedupe_edges() { + // Works around https://github.com/rust-lang/cargo/issues/7985 + Package::new("bitflags", "1.0.0").publish(); + Package::new("manyfeat", "1.0.0") + .feature("f1", &[]) + .feature("f2", &[]) + .feature("f3", &[]) + .dep("bitflags", "1.0") + .publish(); + Package::new("a", "1.0.0") + .feature_dep("manyfeat", "1.0", &["f1"]) + .publish(); + Package::new("b", "1.0.0") + .feature_dep("manyfeat", "1.0", &["f2"]) + .publish(); + Package::new("c", "1.0.0") + .feature_dep("manyfeat", "1.0", &["f3"]) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = "1.0" + b = "1.0" + c = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── a v1.0.0 +│ └── manyfeat v1.0.0 +│ └── bitflags v1.0.0 +├── b v1.0.0 +│ └── manyfeat v1.0.0 (*) +└── c v1.0.0 + └── manyfeat v1.0.0 (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn renamed_deps() { + // Handles renamed dependencies. + Package::new("one", "1.0.0").publish(); + Package::new("two", "1.0.0").publish(); + Package::new("bar", "1.0.0").dep("one", "1.0").publish(); + Package::new("bar", "2.0.0").dep("two", "1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + + [dependencies] + bar1 = {version = "1.0", package="bar"} + bar2 = {version = "2.0", package="bar"} + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +├── bar v1.0.0 +│ └── one v1.0.0 +└── bar v2.0.0 + └── two v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn source_kinds() { + // Handles git and path sources. + Package::new("regdep", "1.0.0").publish(); + let git_project = git::new("gitdep", |p| { + p.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + regdep = "1.0" + pathdep = {{ path = "pathdep" }} + gitdep = {{ git = "{}" }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .file("pathdep/Cargo.toml", &basic_manifest("pathdep", "1.0.0")) + .file("pathdep/src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── gitdep v1.0.0 ([ROOTURL]/gitdep#[..]) +├── pathdep v1.0.0 ([ROOT]/foo/pathdep) +└── regdep v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn features() { + // Exercises a variety of feature behaviors. + Package::new("optdep_default", "1.0.0").publish(); + Package::new("optdep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + + [dependencies] + optdep_default = { version = "1.0", optional = true } + optdep = { version = "1.0", optional = true } + + [features] + default = ["optdep_default"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo) +└── optdep_default v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --no-default-features") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree --all-features") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo) +├── optdep v1.0.0 +└── optdep_default v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --features optdep") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo) +├── optdep v1.0.0 +└── optdep_default v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn filters_target() { + // --target flag + if cross_compile::disabled() { + return; + } + Package::new("targetdep", "1.0.0").publish(); + Package::new("hostdep", "1.0.0").publish(); + Package::new("devdep", "1.0.0").publish(); + Package::new("build_target_dep", "1.0.0").publish(); + Package::new("build_host_dep", "1.0.0") + .target_dep("targetdep", "1.0", alternate()) + .target_dep("hostdep", "1.0", rustc_host()) + .publish(); + Package::new("pm_target", "1.0.0") + .proc_macro(true) + .publish(); + Package::new("pm_host", "1.0.0").proc_macro(true).publish(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [target.'{alt}'.dependencies] + targetdep = "1.0" + pm_target = "1.0" + + [target.'{host}'.dependencies] + hostdep = "1.0" + pm_host = "1.0" + + [target.'{alt}'.dev-dependencies] + devdep = "1.0" + + [target.'{alt}'.build-dependencies] + build_target_dep = "1.0" + + [target.'{host}'.build-dependencies] + build_host_dep = "1.0" + "#, + alt = alternate(), + host = rustc_host() + ), + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── hostdep v1.0.0 +└── pm_host v1.0.0 (proc-macro) +[build-dependencies] +└── build_host_dep v1.0.0 + └── hostdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --target") + .arg(alternate()) + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── pm_target v1.0.0 (proc-macro) +└── targetdep v1.0.0 +[build-dependencies] +└── build_host_dep v1.0.0 + └── hostdep v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --target") + .arg(rustc_host()) + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── hostdep v1.0.0 +└── pm_host v1.0.0 (proc-macro) +[build-dependencies] +└── build_host_dep v1.0.0 + └── hostdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --target=all") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── hostdep v1.0.0 +├── pm_host v1.0.0 (proc-macro) +├── pm_target v1.0.0 (proc-macro) +└── targetdep v1.0.0 +[build-dependencies] +├── build_host_dep v1.0.0 +│ ├── hostdep v1.0.0 +│ └── targetdep v1.0.0 +└── build_target_dep v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + +"#]]) + .run(); + + // no-proc-macro + p.cargo("tree --target=all -e no-proc-macro") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── hostdep v1.0.0 +└── targetdep v1.0.0 +[build-dependencies] +├── build_host_dep v1.0.0 +│ ├── hostdep v1.0.0 +│ └── targetdep v1.0.0 +└── build_target_dep v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn no_selected_target_dependency() { + // --target flag + if cross_compile::disabled() { + return; + } + Package::new("targetdep", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [target.'{alt}'.dependencies] + targetdep = "1.0" + + "#, + alt = alternate(), + ), + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree -i targetdep") + .with_stderr_data(str![[r#" +[WARNING] nothing to print. + +To find dependencies that require specific target platforms, try to use option `--target all` first, and then narrow your search scope accordingly. + +"#]]) + .run(); + p.cargo("tree -i targetdep --target all") + .with_stdout_data(str![[r#" +targetdep v1.0.0 +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn dep_kinds() { + Package::new("inner-devdep", "1.0.0").publish(); + Package::new("inner-builddep", "1.0.0").publish(); + Package::new("inner-normal", "1.0.0").publish(); + Package::new("inner-pm", "1.0.0").proc_macro(true).publish(); + Package::new("inner-buildpm", "1.0.0") + .proc_macro(true) + .publish(); + Package::new("normaldep", "1.0.0") + .dep("inner-normal", "1.0") + .dev_dep("inner-devdep", "1.0") + .build_dep("inner-builddep", "1.0") + .publish(); + Package::new("devdep", "1.0.0") + .dep("inner-normal", "1.0") + .dep("inner-pm", "1.0") + .dev_dep("inner-devdep", "1.0") + .build_dep("inner-builddep", "1.0") + .build_dep("inner-buildpm", "1.0") + .publish(); + Package::new("builddep", "1.0.0") + .dep("inner-normal", "1.0") + .dev_dep("inner-devdep", "1.0") + .build_dep("inner-builddep", "1.0") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + normaldep = "1.0" + + [dev-dependencies] + devdep = "1.0" + + [build-dependencies] + builddep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── normaldep v1.0.0 + └── inner-normal v1.0.0 + [build-dependencies] + └── inner-builddep v1.0.0 +[build-dependencies] +└── builddep v1.0.0 + └── inner-normal v1.0.0 + [build-dependencies] + └── inner-builddep v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + ├── inner-normal v1.0.0 + └── inner-pm v1.0.0 (proc-macro) + [build-dependencies] + ├── inner-builddep v1.0.0 + └── inner-buildpm v1.0.0 (proc-macro) + +"#]]) + .run(); + + p.cargo("tree -e no-dev") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── normaldep v1.0.0 + └── inner-normal v1.0.0 + [build-dependencies] + └── inner-builddep v1.0.0 +[build-dependencies] +└── builddep v1.0.0 + └── inner-normal v1.0.0 + [build-dependencies] + └── inner-builddep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -e normal") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── normaldep v1.0.0 + └── inner-normal v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -e dev,build") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +[build-dependencies] +└── builddep v1.0.0 + [build-dependencies] + └── inner-builddep v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + [build-dependencies] + ├── inner-builddep v1.0.0 + └── inner-buildpm v1.0.0 (proc-macro) + +"#]]) + .run(); + + p.cargo("tree -e dev,build,no-proc-macro") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +[build-dependencies] +└── builddep v1.0.0 + [build-dependencies] + └── inner-builddep v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + [build-dependencies] + └── inner-builddep v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn cyclic_dev_dep() { + // Cyclical dev-dependency and inverse flag. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dev-dependencies] + dev-dep = { path = "dev-dep" } + "#, + ) + .file("src/lib.rs", "") + .file( + "dev-dep/Cargo.toml", + r#" + [package] + name = "dev-dep" + version = "0.1.0" + + [dependencies] + foo = { path=".." } + "#, + ) + .file("dev-dep/src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +[dev-dependencies] +└── dev-dep v0.1.0 ([ROOT]/foo/dev-dep) + └── foo v0.1.0 ([ROOT]/foo) (*) + +"#]]) + .run(); + + p.cargo("tree --invert foo") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── dev-dep v0.1.0 ([ROOT]/foo/dev-dep) + [dev-dependencies] + └── foo v0.1.0 ([ROOT]/foo) (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn invert() { + Package::new("b1", "1.0.0").dep("c", "1.0").publish(); + Package::new("b2", "1.0.0").dep("d", "1.0").publish(); + Package::new("c", "1.0.0").publish(); + Package::new("d", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + b1 = "1.0" + b2 = "1.0" + c = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── b1 v1.0.0 +│ └── c v1.0.0 +├── b2 v1.0.0 +│ └── d v1.0.0 +└── c v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --invert c") + .with_stdout_data(str![[r#" +c v1.0.0 +├── b1 v1.0.0 +│ └── foo v0.1.0 ([ROOT]/foo) +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn invert_with_build_dep() { + // -i for a common dependency between normal and build deps. + Package::new("common", "1.0.0").publish(); + Package::new("bdep", "1.0.0").dep("common", "1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + common = "1.0" + + [build-dependencies] + bdep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── common v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── common v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -i common") + .with_stdout_data(str![[r#" +common v1.0.0 +├── bdep v1.0.0 +│ [build-dependencies] +│ └── foo v0.1.0 ([ROOT]/foo) +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn no_indent() { + let p = make_simple_proj(); + + p.cargo("tree --prefix=none") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +a v1.0.0 +b v1.0.0 +c v1.0.0 +c v1.0.0 +bdep v1.0.0 +b v1.0.0 (*) +devdep v1.0.0 +b v1.0.0 (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn prefix_depth() { + let p = make_simple_proj(); + + p.cargo("tree --prefix=depth") + .with_stdout_data(str![[r#" +0foo v0.1.0 ([ROOT]/foo) +1a v1.0.0 +2b v1.0.0 +3c v1.0.0 +1c v1.0.0 +1bdep v1.0.0 +2b v1.0.0 (*) +1devdep v1.0.0 +2b v1.0.0 (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn no_dedupe() { + let p = make_simple_proj(); + + p.cargo("tree --no-dedupe") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── a v1.0.0 +│ └── b v1.0.0 +│ └── c v1.0.0 +└── c v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── b v1.0.0 + └── c v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 + └── c v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn no_dedupe_cycle() { + // --no-dedupe with a dependency cycle + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dev-dependencies] + bar = {path = "bar"} + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + + [dependencies] + foo = {path=".."} + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +[dev-dependencies] +└── bar v0.1.0 ([ROOT]/foo/bar) + └── foo v0.1.0 ([ROOT]/foo) (*) + +"#]]) + .run(); + + p.cargo("tree --no-dedupe") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +[dev-dependencies] +└── bar v0.1.0 ([ROOT]/foo/bar) + └── foo v0.1.0 ([ROOT]/foo) (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicates() { + Package::new("dog", "1.0.0").publish(); + Package::new("dog", "2.0.0").publish(); + Package::new("cat", "1.0.0").publish(); + Package::new("cat", "2.0.0").publish(); + Package::new("dep", "1.0.0") + .dep("dog", "1.0") + .dep("cat", "1.0") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + + [dependencies] + dog1 = { version = "1.0", package = "dog" } + dog2 = { version = "2.0", package = "dog" } + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + + [dependencies] + dep = "1.0" + cat = "2.0" + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("tree -p a") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo/a) +├── dog v1.0.0 +└── dog v2.0.0 + +"#]]) + .run(); + + p.cargo("tree -p b") + .with_stdout_data(str![[r#" +b v0.1.0 ([ROOT]/foo/b) +├── cat v2.0.0 +└── dep v1.0.0 + ├── cat v1.0.0 + └── dog v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -p a -d") + .with_stdout_data(str![[r#" +dog v1.0.0 +└── a v0.1.0 ([ROOT]/foo/a) + +dog v2.0.0 +└── a v0.1.0 ([ROOT]/foo/a) + +"#]]) + .run(); + + p.cargo("tree -p b -d") + .with_stdout_data(str![[r#" +cat v1.0.0 +└── dep v1.0.0 + └── b v0.1.0 ([ROOT]/foo/b) + +cat v2.0.0 +└── b v0.1.0 ([ROOT]/foo/b) + +"#]]) + .run(); +} + +#[cargo_test] +fn duplicates_with_target() { + // --target flag + if cross_compile::disabled() { + return; + } + Package::new("a", "1.0.0").publish(); + Package::new("dog", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = "1.0" + dog = "1.0" + + [build-dependencies] + a = "1.0" + dog = "1.0" + + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + p.cargo("tree -d").with_stdout_data(str![""]).run(); + + p.cargo("tree -d --target") + .arg(alternate()) + .with_stdout_data(str![""]) + .run(); + + p.cargo("tree -d --target") + .arg(rustc_host()) + .with_stdout_data(str![""]) + .run(); + + p.cargo("tree -d --target=all") + .with_stdout_data(str![""]) + .run(); +} + +#[cargo_test] +fn duplicates_with_proc_macro() { + Package::new("dupe-dep", "1.0.0").publish(); + Package::new("dupe-dep", "2.0.0").publish(); + Package::new("proc", "1.0.0") + .proc_macro(true) + .dep("dupe-dep", "1.0") + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + proc = "1.0" + dupe-dep = "2.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── dupe-dep v2.0.0 +└── proc v1.0.0 (proc-macro) + └── dupe-dep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --duplicates") + .with_stdout_data(str![[r#" +dupe-dep v1.0.0 +└── proc v1.0.0 (proc-macro) + └── foo v0.1.0 ([ROOT]/foo) + +dupe-dep v2.0.0 +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree --duplicates --edges no-proc-macro") + .with_stdout_data(str![""]) + .run(); +} + +#[cargo_test] +fn charset() { + let p = make_simple_proj(); + p.cargo("tree --charset ascii") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +|-- a v1.0.0 +| `-- b v1.0.0 +| `-- c v1.0.0 +`-- c v1.0.0 +[build-dependencies] +`-- bdep v1.0.0 + `-- b v1.0.0 (*) +[dev-dependencies] +`-- devdep v1.0.0 + `-- b v1.0.0 (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn format() { + Package::new("dep", "1.0.0").publish(); + Package::new("other-dep", "1.0.0").publish(); + + Package::new("dep_that_is_awesome", "1.0.0") + .file( + "Cargo.toml", + r#" + [package] + name = "dep_that_is_awesome" + version = "1.0.0" + + [lib] + name = "awesome_dep" + "#, + ) + .file("src/lib.rs", "pub struct Straw;") + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + license = "MIT" + repository = "https://github.com/rust-lang/cargo" + + [dependencies] + dep = {version="1.0", optional=true} + other-dep = {version="1.0", optional=true} + dep_that_is_awesome = {version="1.0", optional=true} + + + [features] + default = ["foo"] + foo = ["bar"] + bar = [] + "#, + ) + .file("src/main.rs", "") + .build(); + + p.cargo("tree --format <<<{p}>>>") + .with_stdout_data(str![[r#" +<<>> + +"#]]) + .run(); + + p.cargo("tree --format {}") + .with_stderr_data(str![[r#" +[ERROR] tree format `{}` not valid + +Caused by: + unsupported pattern `` + +"#]]) + .with_status(101) + .run(); + + p.cargo("tree --format {p}-{{hello}}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo)-{hello} + +"#]]) + .run(); + + p.cargo("tree --format") + .arg("{p} {l} {r}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) MIT https://github.com/rust-lang/cargo + +"#]]) + .run(); + + p.cargo("tree --format") + .arg("{p} {f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) bar,default,foo + +"#]]) + .run(); + + p.cargo("tree --all-features --format") + .arg("{p} [{f}]") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) [bar,default,dep,dep_that_is_awesome,foo,other-dep] +├── dep v1.0.0 [] +├── dep_that_is_awesome v1.0.0 [] +└── other-dep v1.0.0 [] + +"#]]) + .run(); + + p.cargo("tree") + .arg("--features=other-dep,dep_that_is_awesome") + .arg("--format={lib}") + .with_stdout_data(str![[r#" + +├── awesome_dep +└── other_dep + +"#]]) + .run(); +} + +#[cargo_test] +fn dev_dep_feature() { + // New feature resolver with optional dep + Package::new("optdep", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("optdep", "1.0").optional(true)) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dev-dependencies] + bar = { version = "1.0", features = ["optdep"] } + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Old behavior. + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + └── optdep v1.0.0 +[dev-dependencies] +└── bar v1.0.0 (*) + +"#]]) + .run(); + + p.cargo("tree -e normal") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + └── optdep v1.0.0 + +"#]]) + .run(); + + // New behavior. + switch_to_resolver_2(&p); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + └── optdep v1.0.0 +[dev-dependencies] +└── bar v1.0.0 (*) + +"#]]) + .run(); + + p.cargo("tree -e normal") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn host_dep_feature() { + // New feature resolver with optional build dep + Package::new("optdep", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("optdep", "1.0").optional(true)) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [build-dependencies] + bar = { version = "1.0", features = ["optdep"] } + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + .build(); + + // Old behavior + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + └── optdep v1.0.0 +[build-dependencies] +└── bar v1.0.0 (*) + +"#]]) + .run(); + + // -p + p.cargo("tree -p bar") + .with_stdout_data(str![[r#" +bar v1.0.0 +└── optdep v1.0.0 + +"#]]) + .run(); + + // invert + p.cargo("tree -i optdep") + .with_stdout_data(str![[r#" +optdep v1.0.0 +└── bar v1.0.0 + └── foo v0.1.0 ([ROOT]/foo) + [build-dependencies] + └── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + // New behavior. + switch_to_resolver_2(&p); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 +[build-dependencies] +└── bar v1.0.0 + └── optdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -p bar") + .with_stdout_data(str![[r#" +bar v1.0.0 + +bar v1.0.0 +└── optdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -i optdep") + .with_stdout_data(str![[r#" +optdep v1.0.0 +└── bar v1.0.0 + [build-dependencies] + └── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + // Check that -d handles duplicates with features. + p.cargo("tree -d") + .with_stdout_data(str![[r#" +bar v1.0.0 +└── foo v0.1.0 ([ROOT]/foo) + +bar v1.0.0 +[build-dependencies] +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn proc_macro_features() { + // New feature resolver with a proc-macro + Package::new("optdep", "1.0.0").publish(); + Package::new("somedep", "1.0.0") + .add_dep(Dependency::new("optdep", "1.0").optional(true)) + .publish(); + Package::new("pm", "1.0.0") + .proc_macro(true) + .feature_dep("somedep", "1.0", &["optdep"]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + pm = "1.0" + somedep = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Old behavior + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── pm v1.0.0 (proc-macro) +│ └── somedep v1.0.0 +│ └── optdep v1.0.0 +└── somedep v1.0.0 (*) + +"#]]) + .run(); + + // Old behavior + no-proc-macro + p.cargo("tree -e no-proc-macro") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── somedep v1.0.0 + └── optdep v1.0.0 + +"#]]) + .run(); + + // -p + p.cargo("tree -p somedep") + .with_stdout_data(str![[r#" +somedep v1.0.0 +└── optdep v1.0.0 + +"#]]) + .run(); + + // -p -e no-proc-macro + p.cargo("tree -p somedep -e no-proc-macro") + .with_stdout_data(str![[r#" +somedep v1.0.0 +└── optdep v1.0.0 + +"#]]) + .run(); + + // invert + p.cargo("tree -i somedep") + .with_stdout_data(str![[r#" +somedep v1.0.0 +├── foo v0.1.0 ([ROOT]/foo) +└── pm v1.0.0 (proc-macro) + └── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + // invert + no-proc-macro + p.cargo("tree -i somedep -e no-proc-macro") + .with_stdout_data(str![[r#" +somedep v1.0.0 +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + // New behavior. + switch_to_resolver_2(&p); + + // Note the missing (*) + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── pm v1.0.0 (proc-macro) +│ └── somedep v1.0.0 +│ └── optdep v1.0.0 +└── somedep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -e no-proc-macro") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── somedep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -p somedep") + .with_stdout_data(str![[r#" +somedep v1.0.0 + +somedep v1.0.0 +└── optdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -i somedep") + .with_stdout_data(str![[r#" +somedep v1.0.0 +└── foo v0.1.0 ([ROOT]/foo) + +somedep v1.0.0 +└── pm v1.0.0 (proc-macro) + └── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree -i somedep -e no-proc-macro") + .with_stdout_data(str![[r#" +somedep v1.0.0 +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn itarget_opt_dep() { + // New feature resolver with optional target dep + Package::new("optdep", "1.0.0").publish(); + Package::new("common", "1.0.0") + .add_dep(Dependency::new("optdep", "1.0").optional(true)) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + + [dependencies] + common = "1.0" + + [target.'cfg(whatever)'.dependencies] + common = { version = "1.0", features = ["optdep"] } + + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Old behavior + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +└── common v1.0.0 + └── optdep v1.0.0 + +"#]]) + .run(); + + // New behavior. + switch_to_resolver_2(&p); + + p.cargo("tree") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +└── common v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn ambiguous_name() { + // -p that is ambiguous. + Package::new("dep", "1.0.0").publish(); + Package::new("dep", "2.0.0").publish(); + Package::new("bar", "1.0.0").dep("dep", "2.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + dep = "1.0" + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -p dep") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[ADDING] dep v1.0.0 (available: v2.0.0) +[DOWNLOADING] crates ... +[DOWNLOADED] dep v2.0.0 (registry `dummy-registry`) +[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[ERROR] There are multiple `dep` packages in your project, and the specification `dep` is ambiguous. +Please re-run this command with one of the following specifications: + dep@1.0.0 + dep@2.0.0 + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn workspace_features_are_local() { + // The features for workspace packages should be the same as `cargo build` + // (i.e., the features selected depend on the "current" package). + Package::new("optdep", "1.0.0").publish(); + Package::new("somedep", "1.0.0") + .add_dep(Dependency::new("optdep", "1.0").optional(true)) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + + [dependencies] + somedep = {version="1.0", features=["optdep"]} + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + + [dependencies] + somedep = "1.0" + + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("tree") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo/a) +└── somedep v1.0.0 + └── optdep v1.0.0 + +b v0.1.0 ([ROOT]/foo/b) +└── somedep v1.0.0 (*) + +"#]]) + .run(); + + p.cargo("tree -p a") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo/a) +└── somedep v1.0.0 + └── optdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -p b") + .with_stdout_data(str![[r#" +b v0.1.0 ([ROOT]/foo/b) +└── somedep v1.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn unknown_edge_kind() { + let p = project() + .file("Cargo.toml", "") + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -e unknown") + .with_stderr_data(str![[r#" +[ERROR] unknown edge kind `unknown`, valid values are "normal", "build", "dev", "no-normal", "no-build", "no-dev", "no-proc-macro", "features", or "all" + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn mixed_no_edge_kinds() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -e no-build,normal") + .with_stderr_data(str![[r#" +[ERROR] `normal` dependency kind cannot be mixed with "no-normal", "no-build", or "no-dev" dependency kinds + +"#]]) + .with_status(101) + .run(); + + // `no-proc-macro` can be mixed with others + p.cargo("tree -e no-proc-macro,normal") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn depth_limit() { + let p = make_simple_proj(); + + p.cargo("tree --depth 0") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +[build-dependencies] +[dev-dependencies] + +"#]]) + .run(); + + p.cargo("tree --depth 1") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── a v1.0.0 +└── c v1.0.0 +[build-dependencies] +└── bdep v1.0.0 +[dev-dependencies] +└── devdep v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --depth 2") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── a v1.0.0 +│ └── b v1.0.0 +└── c v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── b v1.0.0 (*) +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) + +"#]]) + .run(); + + // specify a package + p.cargo("tree -p bdep --depth 1") + .with_stdout_data(str![[r#" +bdep v1.0.0 +└── b v1.0.0 + +"#]]) + .run(); + + // different prefix + p.cargo("tree --depth 1 --prefix depth") + .with_stdout_data(str![[r#" +0foo v0.1.0 ([ROOT]/foo) +1a v1.0.0 +1c v1.0.0 +1bdep v1.0.0 +1devdep v1.0.0 + +"#]]) + .run(); + + // with edge-kinds + p.cargo("tree --depth 1 -e no-dev") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── a v1.0.0 +└── c v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + +"#]]) + .run(); + + // invert + p.cargo("tree --depth 1 --invert c") + .with_stdout_data(str![[r#" +c v1.0.0 +├── b v1.0.0 +└── foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn depth_workspace() { + Package::new("somedep", "1.0.0").publish(); + Package::new("otherdep", "1.0.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b", "c"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "1.0.0")) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + + [dependencies] + c = { path = "../c" } + somedep = "1" + "#, + ) + .file("b/src/lib.rs", "") + .file( + "c/Cargo.toml", + r#" + [package] + name = "c" + version = "0.1.0" + + [dependencies] + somedep = "1" + otherdep = "1" + "#, + ) + .file("c/src/lib.rs", "") + .build(); + + p.cargo("tree --depth workspace") + .with_stdout_data(str![[r#" +a v1.0.0 ([ROOT]/foo/a) + +b v0.1.0 ([ROOT]/foo/b) +└── c v0.1.0 ([ROOT]/foo/c) + +c v0.1.0 ([ROOT]/foo/c) (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn prune() { + let p = make_simple_proj(); + + p.cargo("tree --prune c") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── a v1.0.0 + └── b v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── b v1.0.0 (*) +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) + +"#]]) + .run(); + + // multiple prune + p.cargo("tree --prune c --prune bdep") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── a v1.0.0 + └── b v1.0.0 +[build-dependencies] +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) + +"#]]) + .run(); + + // with edge-kinds + p.cargo("tree --prune c -e normal") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── a v1.0.0 + └── b v1.0.0 + +"#]]) + .run(); + + // pruning self does not works + p.cargo("tree --prune foo") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── a v1.0.0 +│ └── b v1.0.0 +│ └── c v1.0.0 +└── c v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── b v1.0.0 (*) +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) + +"#]]) + .run(); + + // dep not exist + p.cargo("tree --prune no-dep") + .with_stderr_data(str![[r#" +[ERROR] package ID specification `no-dep` did not match any packages + +[HELP] a package with a similar name exists: `bdep` + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn cyclic_features() { + // Check for stack overflow with cyclic features (oops!). + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + + [features] + a = ["b"] + b = ["a"] + default = ["a"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -e features") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree -e features -i foo") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +├── foo feature "a" +│ ├── foo feature "b" +│ │ └── foo feature "a" (*) +│ └── foo feature "default" (command-line) +├── foo feature "b" (*) +└── foo feature "default" (command-line) + +"#]]) + .run(); +} + +#[cargo_test] +fn dev_dep_cycle_with_feature() { + // Cycle with features and a dev-dependency. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + + [dev-dependencies] + bar = { path = "bar" } + + [features] + a = ["bar/feat1"] + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "1.0.0" + + [dependencies] + foo = { path = ".." } + + [features] + feat1 = ["foo/a"] + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("tree -e features --features a") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +[dev-dependencies] +└── bar feature "default" + └── bar v1.0.0 ([ROOT]/foo/bar) + └── foo feature "default" (command-line) + └── foo v1.0.0 ([ROOT]/foo) (*) + +"#]]) + .run(); + + p.cargo("tree -e features --features a -i foo") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +├── foo feature "a" (command-line) +│ └── bar feature "feat1" +│ └── foo feature "a" (command-line) (*) +└── foo feature "default" (command-line) + └── bar v1.0.0 ([ROOT]/foo/bar) + ├── bar feature "default" + │ [dev-dependencies] + │ └── foo v1.0.0 ([ROOT]/foo) (*) + └── bar feature "feat1" (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn dev_dep_cycle_with_feature_nested() { + // Checks for an issue where a cyclic dev dependency tries to activate a + // feature on its parent that tries to activate the feature back on the + // dev-dependency. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + + [dev-dependencies] + bar = { path = "bar" } + + [features] + a = ["bar/feat1"] + b = ["a"] + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "1.0.0" + + [dependencies] + foo = { path = ".." } + + [features] + feat1 = ["foo/b"] + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("tree -e features") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +[dev-dependencies] +└── bar feature "default" + └── bar v1.0.0 ([ROOT]/foo/bar) + └── foo feature "default" (command-line) + └── foo v1.0.0 ([ROOT]/foo) (*) + +"#]]) + .run(); + + p.cargo("tree -e features --features a -i foo") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +├── foo feature "a" (command-line) +│ └── foo feature "b" +│ └── bar feature "feat1" +│ └── foo feature "a" (command-line) (*) +├── foo feature "b" (*) +└── foo feature "default" (command-line) + └── bar v1.0.0 ([ROOT]/foo/bar) + ├── bar feature "default" + │ [dev-dependencies] + │ └── foo v1.0.0 ([ROOT]/foo) (*) + └── bar feature "feat1" (*) + +"#]]) + .run(); + + p.cargo("tree -e features --features b -i foo") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +├── foo feature "a" +│ └── foo feature "b" (command-line) +│ └── bar feature "feat1" +│ └── foo feature "a" (*) +├── foo feature "b" (command-line) (*) +└── foo feature "default" (command-line) + └── bar v1.0.0 ([ROOT]/foo/bar) + ├── bar feature "default" + │ [dev-dependencies] + │ └── foo v1.0.0 ([ROOT]/foo) (*) + └── bar feature "feat1" (*) + +"#]]) + .run(); + + p.cargo("tree -e features --features bar/feat1 -i foo") + .with_stdout_data(str![[r#" +foo v1.0.0 ([ROOT]/foo) +├── foo feature "a" +│ └── foo feature "b" +│ └── bar feature "feat1" (command-line) +│ └── foo feature "a" (*) +├── foo feature "b" (*) +└── foo feature "default" (command-line) + └── bar v1.0.0 ([ROOT]/foo/bar) + ├── bar feature "default" + │ [dev-dependencies] + │ └── foo v1.0.0 ([ROOT]/foo) (*) + └── bar feature "feat1" (command-line) (*) + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree_graph_features.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree_graph_features.rs new file mode 100644 index 000000000..313afa72c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/tree_graph_features.rs @@ -0,0 +1,352 @@ +//! Tests for the `cargo tree` command with -e features option. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::str; + +#[cargo_test] +fn dep_feature_various() { + // Checks different ways of setting features via dependencies. + Package::new("optdep", "1.0.0") + .feature("default", &["cat"]) + .feature("cat", &[]) + .publish(); + Package::new("defaultdep", "1.0.0") + .feature("default", &["f1"]) + .feature("f1", &["optdep"]) + .add_dep(Dependency::new("optdep", "1.0").optional(true)) + .publish(); + Package::new("nodefaultdep", "1.0.0") + .feature("default", &["f1"]) + .feature("f1", &[]) + .publish(); + Package::new("nameddep", "1.0.0") + .add_dep(Dependency::new("serde", "1.0").optional(true)) + .feature("default", &["serde-stuff"]) + .feature("serde-stuff", &["serde/derive"]) + .feature("vehicle", &["car"]) + .feature("car", &[]) + .publish(); + Package::new("serde_derive", "1.0.0").publish(); + Package::new("serde", "1.0.0") + .feature("derive", &["serde_derive"]) + .add_dep(Dependency::new("serde_derive", "1.0").optional(true)) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + defaultdep = "1.0" + nodefaultdep = {version="1.0", default-features = false} + nameddep = {version="1.0", features = ["vehicle", "serde"]} + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -e features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── nodefaultdep v1.0.0 +├── defaultdep feature "default" +│ ├── defaultdep v1.0.0 +│ │ └── optdep feature "default" +│ │ ├── optdep v1.0.0 +│ │ └── optdep feature "cat" +│ │ └── optdep v1.0.0 +│ └── defaultdep feature "f1" +│ ├── defaultdep v1.0.0 (*) +│ └── defaultdep feature "optdep" +│ └── defaultdep v1.0.0 (*) +├── nameddep feature "default" +│ ├── nameddep v1.0.0 +│ │ └── serde feature "default" +│ │ └── serde v1.0.0 +│ │ └── serde_derive feature "default" +│ │ └── serde_derive v1.0.0 +│ └── nameddep feature "serde-stuff" +│ ├── nameddep v1.0.0 (*) +│ ├── nameddep feature "serde" +│ │ └── nameddep v1.0.0 (*) +│ └── serde feature "derive" +│ ├── serde v1.0.0 (*) +│ └── serde feature "serde_derive" +│ └── serde v1.0.0 (*) +├── nameddep feature "serde" (*) +└── nameddep feature "vehicle" + ├── nameddep v1.0.0 (*) + └── nameddep feature "car" + └── nameddep v1.0.0 (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn graph_features_ws_interdependent() { + // A workspace with interdependent crates. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a", "b"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + + [dependencies] + b = {path="../b", features=["feat2"]} + + [features] + default = ["a1"] + a1 = [] + a2 = [] + "#, + ) + .file("a/src/lib.rs", "") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + + [features] + default = ["feat1"] + feat1 = [] + feat2 = [] + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("tree -e features") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo/a) +├── b feature "default" (command-line) +│ ├── b v0.1.0 ([ROOT]/foo/b) +│ └── b feature "feat1" +│ └── b v0.1.0 ([ROOT]/foo/b) +└── b feature "feat2" + └── b v0.1.0 ([ROOT]/foo/b) + +b v0.1.0 ([ROOT]/foo/b) + +"#]]) + .run(); + + p.cargo("tree -e features -i a -i b") + .with_stdout_data(str![[r#" +a v0.1.0 ([ROOT]/foo/a) +├── a feature "a1" +│ └── a feature "default" (command-line) +└── a feature "default" (command-line) + +b v0.1.0 ([ROOT]/foo/b) +├── b feature "default" (command-line) +│ └── a v0.1.0 ([ROOT]/foo/a) (*) +├── b feature "feat1" +│ └── b feature "default" (command-line) (*) +└── b feature "feat2" + └── a v0.1.0 ([ROOT]/foo/a) (*) + +"#]]) + .run(); +} + +#[cargo_test] +fn slash_feature_name() { + // dep_name/feat_name syntax + Package::new("opt", "1.0.0").feature("feat1", &[]).publish(); + Package::new("notopt", "1.0.0") + .feature("cat", &[]) + .feature("animal", &["cat"]) + .publish(); + Package::new("opt2", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + opt = {version = "1.0", optional=true} + opt2 = {version = "1.0", optional=true} + notopt = "1.0" + + [features] + f1 = ["opt/feat1", "notopt/animal"] + f2 = ["f1"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("tree -e features --features f1") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── notopt feature "default" +│ └── notopt v1.0.0 +└── opt feature "default" + └── opt v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -e features --features f1 -i foo") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── foo feature "default" (command-line) +├── foo feature "f1" (command-line) +└── foo feature "opt" + └── foo feature "f1" (command-line) + +"#]]) + .run(); + + p.cargo("tree -e features --features f1 -i notopt") + .with_stdout_data(str![[r#" +notopt v1.0.0 +├── notopt feature "animal" +│ └── foo feature "f1" (command-line) +├── notopt feature "cat" +│ └── notopt feature "animal" (*) +└── notopt feature "default" + └── foo v0.1.0 ([ROOT]/foo) + ├── foo feature "default" (command-line) + ├── foo feature "f1" (command-line) + └── foo feature "opt" + └── foo feature "f1" (command-line) + +"#]]) + .run(); + + p.cargo("tree -e features --features notopt/animal -i notopt") + .with_stdout_data(str![[r#" +notopt v1.0.0 +├── notopt feature "animal" (command-line) +├── notopt feature "cat" +│ └── notopt feature "animal" (command-line) +└── notopt feature "default" + └── foo v0.1.0 ([ROOT]/foo) + └── foo feature "default" (command-line) + +"#]]) + .run(); + + p.cargo("tree -e features --all-features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── notopt feature "default" +│ └── notopt v1.0.0 +├── opt feature "default" +│ └── opt v1.0.0 +└── opt2 feature "default" + └── opt2 v1.0.0 + +"#]]) + .run(); + + p.cargo("tree -e features --all-features -i opt2") + .with_stdout_data(str![[r#" +opt2 v1.0.0 +└── opt2 feature "default" + └── foo v0.1.0 ([ROOT]/foo) + ├── foo feature "default" (command-line) + ├── foo feature "f1" (command-line) + │ └── foo feature "f2" (command-line) + ├── foo feature "f2" (command-line) + ├── foo feature "opt" (command-line) + │ └── foo feature "f1" (command-line) (*) + └── foo feature "opt2" (command-line) + +"#]]) + .run(); +} + +#[cargo_test] +fn features_enables_inactive_target() { + // Features that enable things on targets that are not enabled. + Package::new("optdep", "1.0.0") + .feature("feat1", &[]) + .publish(); + Package::new("dep1", "1.0.0") + .feature("somefeat", &[]) + .publish(); + Package::new("dep2", "1.0.0") + .add_dep( + Dependency::new("optdep", "1.0.0") + .optional(true) + .target("cfg(whatever)"), + ) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [target.'cfg(whatever)'.dependencies] + optdep = {version="1.0", optional=true} + dep1 = "1.0" + + [dependencies] + dep2 = "1.0" + + [features] + f1 = ["optdep"] + f2 = ["optdep/feat1"] + f3 = ["dep1/somefeat"] + f4 = ["dep2/optdep"] + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("tree -e features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── dep2 feature "default" + └── dep2 v1.0.0 + +"#]]) + .run(); + p.cargo("tree -e features --all-features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── dep2 feature "default" + └── dep2 v1.0.0 + +"#]]) + .run(); + p.cargo("tree -e features --all-features --target=all") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +├── dep1 feature "default" +│ └── dep1 v1.0.0 +├── dep2 feature "default" +│ └── dep2 v1.0.0 +│ └── optdep feature "default" +│ └── optdep v1.0.0 +└── optdep feature "default" (*) + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/unit_graph.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/unit_graph.rs new file mode 100644 index 000000000..cccc79f12 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/unit_graph.rs @@ -0,0 +1,236 @@ +//! Tests for --unit-graph option. + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry::Package; +use cargo_test_support::str; + +#[cargo_test] +fn gated() { + let p = project().file("src/lib.rs", "").build(); + p.cargo("build --unit-graph") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `--unit-graph` flag is unstable, and only available on the nightly channel of Cargo, but this is the `stable` channel +See https://doc.rust-lang.org/book/[..].html for more information about Rust release channels. +See https://github.com/rust-lang/cargo/issues/8002 for more information about the `--unit-graph` flag. + +"#]]) + .run(); +} + +#[cargo_test] +fn simple() { + Package::new("a", "1.0.0") + .dep("b", "1.0") + .feature("feata", &["b/featb"]) + .publish(); + Package::new("b", "1.0.0") + .dep("c", "1.0") + .feature("featb", &["c/featc"]) + .publish(); + Package::new("c", "1.0.0").feature("featc", &[]).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("build --features a/feata --unit-graph -Zunstable-options") + .masquerade_as_nightly_cargo(&["unit-graph"]) + .with_stdout_data( + str![[r#" +{ + "roots": [ + 3 + ], + "units": [ + { + "dependencies": [ + { + "extern_crate_name": "b", + "index": 1, + "noprelude": false, + "public": false + } + ], + "features": [ + "feata" + ], + "mode": "build", + "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, + "profile": { + "codegen_backend": null, + "codegen_units": null, + "debug_assertions": true, + "debuginfo": 2, + "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false, + "split_debuginfo": "{...}", + "strip": "{...}" + }, + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "a", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/a-1.0.0/src/lib.rs", + "test": true + } + }, + { + "dependencies": [ + { + "extern_crate_name": "c", + "index": 2, + "noprelude": false, + "public": false + } + ], + "features": [ + "featb" + ], + "mode": "build", + "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, + "profile": { + "codegen_backend": null, + "codegen_units": null, + "debug_assertions": true, + "debuginfo": 2, + "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false, + "split_debuginfo": "{...}", + "strip": "{...}" + }, + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "b", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/b-1.0.0/src/lib.rs", + "test": true + } + }, + { + "dependencies": [], + "features": [ + "featc" + ], + "mode": "build", + "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "platform": null, + "profile": { + "codegen_backend": null, + "codegen_units": null, + "debug_assertions": true, + "debuginfo": 2, + "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false, + "split_debuginfo": "{...}", + "strip": "{...}" + }, + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "c", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/c-1.0.0/src/lib.rs", + "test": true + } + }, + { + "dependencies": [ + { + "extern_crate_name": "a", + "index": 0, + "noprelude": false, + "public": false + } + ], + "features": [], + "mode": "build", + "pkg_id": "foo 0.1.0 (path+[ROOTURL]/foo)", + "platform": null, + "profile": { + "codegen_backend": null, + "codegen_units": null, + "debug_assertions": true, + "debuginfo": 2, + "incremental": false, + "lto": "false", + "name": "dev", + "opt_level": "0", + "overflow_checks": true, + "panic": "unwind", + "rpath": false, + "split_debuginfo": "{...}", + "strip": "{...}" + }, + "target": { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "foo", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + } + ], + "version": 1 +} +"#]] + .is_json(), + ) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/update.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/update.rs new file mode 100644 index 000000000..87c36293d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/update.rs @@ -0,0 +1,2711 @@ +//! Tests for the `cargo update` command. + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self}; +use cargo_test_support::registry::{Dependency, Package}; +use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project, str}; + +#[cargo_test] +fn minor_update_two_places() { + Package::new("log", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + log = "0.1" + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + log = "0.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + Package::new("log", "0.1.1").publish(); + + p.change_file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + log = "0.1.1" + "#, + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn transitive_minor_update() { + Package::new("log", "0.1.0").publish(); + Package::new("serde", "0.1.0").dep("log", "0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.1" + log = "0.1" + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + Package::new("log", "0.1.1").publish(); + Package::new("serde", "0.1.1").dep("log", "0.1.1").publish(); + + // Note that `serde` isn't actually updated here! The default behavior for + // `update` right now is to as conservatively as possible attempt to satisfy + // an update. In this case we previously locked the dependency graph to `log + // 0.1.0`, but nothing on the command line says we're allowed to update + // that. As a result the update of `serde` here shouldn't update to `serde + // 0.1.1` as that would also force an update to `log 0.1.1`. + // + // Also note that this is probably counterintuitive and weird. We may wish + // to change this one day. + p.cargo("update serde") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 0 packages to latest compatible versions +[NOTE] pass `--verbose` to see 2 unchanged dependencies behind latest + +"#]]) + .run(); +} + +#[cargo_test] +fn conservative() { + Package::new("log", "0.1.0").publish(); + Package::new("serde", "0.1.0").dep("log", "0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.1" + log = "0.1" + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + Package::new("log", "0.1.1").publish(); + Package::new("serde", "0.1.1").dep("log", "0.1").publish(); + + p.cargo("update serde") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] serde v0.1.0 -> v0.1.1 +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]]) + .run(); +} + +#[cargo_test] +fn update_via_new_dep() { + Package::new("log", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + log = "0.1" + # foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + log = "0.1.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + Package::new("log", "0.1.1").publish(); + + p.uncomment_root_manifest(); + p.cargo("check").env("CARGO_LOG", "cargo=trace").run(); +} + +#[cargo_test] +fn update_via_new_member() { + Package::new("log", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [workspace] + # members = [ "foo" ] + + [dependencies] + log = "0.1" + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + log = "0.1.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + Package::new("log", "0.1.1").publish(); + + p.uncomment_root_manifest(); + p.cargo("check").run(); +} + +#[cargo_test] +fn add_dep_deep_new_requirement() { + Package::new("log", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + log = "0.1" + # bar = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + Package::new("log", "0.1.1").publish(); + Package::new("bar", "0.1.0").dep("log", "0.1.1").publish(); + + p.uncomment_root_manifest(); + p.cargo("check").run(); +} + +#[cargo_test] +fn everything_real_deep() { + Package::new("log", "0.1.0").publish(); + Package::new("foo", "0.1.0").dep("log", "0.1").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + foo = "0.1" + # bar = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + Package::new("log", "0.1.1").publish(); + Package::new("bar", "0.1.0").dep("log", "0.1.1").publish(); + + p.uncomment_root_manifest(); + p.cargo("check").run(); +} + +#[cargo_test] +fn change_package_version() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "a-foo" + version = "0.2.0-alpha" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar", version = "0.2.0-alpha" } + "#, + ) + .file("src/lib.rs", "") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0-alpha")) + .file("bar/src/lib.rs", "") + .file( + "Cargo.lock", + r#" + [[package]] + name = "foo" + version = "0.2.0" + dependencies = ["bar 0.2.0"] + + [[package]] + name = "bar" + version = "0.2.0" + "#, + ) + .build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn update_precise() { + Package::new("serde", "0.1.0").publish(); + Package::new("serde", "0.2.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.2" + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + Package::new("serde", "0.2.0").publish(); + + p.cargo("update serde:0.2.1 --precise 0.2.0") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNGRADING] serde v0.2.1 -> v0.2.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_precise_mismatched() { + Package::new("serde", "1.2.0").publish(); + Package::new("serde", "1.2.1").publish(); + Package::new("serde", "1.6.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "~1.2" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check").run(); + + // `1.6.0` does not match `"~1.2"` + p.cargo("update serde:1.2 --precise 1.6.0") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] failed to select a version for the requirement `serde = "~1.2"` +candidate versions found which didn't match: 1.6.0 +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `bar v0.0.1 ([ROOT]/foo)` +perhaps a crate was updated and forgotten to be re-vendored? + +"#]]) + .with_status(101) + .run(); + + // `1.9.0` does not exist + p.cargo("update serde:1.2 --precise 1.9.0") + // This terrible error message has been the same for a long time. A fix is more than welcome! + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `serde` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `bar v0.0.1 ([ROOT]/foo)` + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn update_precise_build_metadata() { + Package::new("serde", "0.0.1+first").publish(); + Package::new("serde", "0.0.1+second").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.0" + edition = "2015" + + [dependencies] + serde = "0.0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + p.cargo("update serde --precise 0.0.1+first").run(); + + p.cargo("update serde --precise 0.0.1+second") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] serde v0.0.1+first -> v0.0.1+second + +"#]]) + .run(); + + // This is not considered "Downgrading". Build metadata are not assumed to + // be ordered. + p.cargo("update serde --precise 0.0.1+first") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] serde v0.0.1+second -> v0.0.1+first + +"#]]) + .run(); +} + +#[cargo_test] +fn update_precise_do_not_force_update_deps() { + 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" + edition = "2015" + 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") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] serde v0.2.1 -> v0.2.2 +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]]) + .run(); +} + +#[cargo_test] +fn update_recursive() { + 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" + edition = "2015" + 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 --recursive") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[UPDATING] log v0.1.0 -> v0.1.1 +[UPDATING] serde v0.2.1 -> v0.2.2 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_aggressive_alias_for_recursive() { + 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" + edition = "2015" + 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 --aggressive") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions +[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" + edition = "2015" + 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_data(str![[r#" +[ERROR] the argument '--precise ' cannot be used with '--recursive' + +Usage: cargo[EXE] update --precise ]> + +For more information, try '--help'. + +"#]]) + .run(); +} + +// cargo update should respect its arguments even without a lockfile. +// See issue "Running cargo update without a Cargo.lock ignores arguments" +// at . +#[cargo_test] +fn update_precise_first_run() { + Package::new("serde", "0.1.0").publish(); + Package::new("serde", "0.2.0").publish(); + Package::new("serde", "0.2.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + + [dependencies] + serde = "0.2" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update serde --precise 0.2.0") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[DOWNGRADING] serde v0.2.1 -> v0.2.0 + +"#]]) + .run(); + + // Assert `cargo metadata` shows serde 0.2.0 + p.cargo("metadata") + .with_stdout_data( + str![[r#" +{ + "metadata": null, + "packages": [ + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [ + { + "features": [], + "kind": null, + "name": "serde", + "optional": false, + "registry": null, + "rename": null, + "req": "^0.2", + "source": "registry+https://github.com/rust-lang/crates.io-index", + "target": null, + "uses_default_features": true + } + ], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "path+[ROOTURL]/foo#bar@0.0.1", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/foo/Cargo.toml", + "metadata": null, + "name": "bar", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": null, + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "bar", + "src_path": "[ROOT]/foo/src/lib.rs", + "test": true + } + ], + "version": "0.0.1" + }, + { + "authors": [], + "categories": [], + "default_run": null, + "dependencies": [], + "description": null, + "documentation": null, + "edition": "2015", + "features": {}, + "homepage": null, + "id": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0", + "keywords": [], + "license": null, + "license_file": null, + "links": null, + "manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/serde-0.2.0/Cargo.toml", + "metadata": null, + "name": "serde", + "publish": null, + "readme": null, + "repository": null, + "rust_version": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "targets": [ + { + "crate_types": [ + "lib" + ], + "doc": true, + "doctest": true, + "edition": "2015", + "kind": [ + "lib" + ], + "name": "serde", + "src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/serde-0.2.0/src/lib.rs", + "test": true + } + ], + "version": "0.2.0" + } + ], + "resolve": { + "nodes": [ + { + "dependencies": [ + "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0" + ], + "deps": [ + { + "dep_kinds": [ + { + "kind": null, + "target": null + } + ], + "name": "serde", + "pkg": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0" + } + ], + "features": [], + "id": "path+[ROOTURL]/foo#bar@0.0.1" + }, + { + "dependencies": [], + "deps": [], + "features": [], + "id": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0" + } + ], + "root": "path+[ROOTURL]/foo#bar@0.0.1" + }, + "target_directory": "[ROOT]/foo/target", + "version": 1, + "workspace_default_members": [ + "path+[ROOTURL]/foo#bar@0.0.1" + ], + "workspace_members": [ + "path+[ROOTURL]/foo#bar@0.0.1" + ], + "workspace_root": "[ROOT]/foo" +} +"#]] + .is_json(), + ) + .run(); + + p.cargo("update serde --precise 0.2.0") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index + +"#]]) + .run(); +} + +#[cargo_test] +fn preserve_top_comment() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("update").run(); + + let lockfile = p.read_lockfile(); + assert!(lockfile.starts_with("# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n")); + + let mut lines = lockfile.lines().collect::>(); + lines.insert(2, "# some other comment"); + let mut lockfile = lines.join("\n"); + lockfile.push('\n'); // .lines/.join loses the last newline + println!("saving Cargo.lock contents:\n{}", lockfile); + + p.change_file("Cargo.lock", &lockfile); + + p.cargo("update").run(); + + let lockfile2 = p.read_lockfile(); + println!("loaded Cargo.lock contents:\n{}", lockfile2); + + assert_eq!(lockfile, lockfile2); +} + +#[cargo_test] +fn dry_run_update() { + Package::new("log", "0.1.0").publish(); + Package::new("serde", "0.1.0").dep("log", "0.1").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.1" + log = "0.1" + foo = { path = "foo" } + "#, + ) + .file("src/lib.rs", "") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + serde = "0.1" + "#, + ) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("check").run(); + let old_lockfile = p.read_lockfile(); + + Package::new("log", "0.1.1").publish(); + Package::new("serde", "0.1.1").dep("log", "0.1").publish(); + + p.cargo("update serde --dry-run") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] serde v0.1.0 -> v0.1.1 +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest +[WARNING] not updating lockfile due to dry run + +"#]]) + .run(); + let new_lockfile = p.read_lockfile(); + assert_eq!(old_lockfile, new_lockfile) +} + +#[cargo_test] +fn workspace_only() { + let p = project().file("src/main.rs", "fn main() {}").build(); + p.cargo("generate-lockfile").run(); + let lock1 = p.read_lockfile(); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + authors = [] + version = "0.0.2" + edition = "2015" + "#, + ); + p.cargo("update --workspace").run(); + let lock2 = p.read_lockfile(); + + assert_ne!(lock1, lock2); + assert!(lock1.contains("0.0.1")); + assert!(lock2.contains("0.0.2")); + assert!(!lock1.contains("0.0.2")); + assert!(!lock2.contains("0.0.1")); +} + +#[cargo_test] +fn precise_with_build_metadata() { + // +foo syntax shouldn't be necessary with --precise + Package::new("bar", "0.1.0+extra-stuff.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("generate-lockfile").run(); + Package::new("bar", "0.1.1+extra-stuff.1").publish(); + Package::new("bar", "0.1.2+extra-stuff.2").publish(); + + p.cargo("update bar --precise 0.1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid version format for precise version `0.1` + +Caused by: + unexpected end of input while parsing minor version number + +"#]]) + .run(); + + p.cargo("update bar --precise 0.1.1+does-not-match") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `bar` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); + + p.cargo("update bar --precise 0.1.1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] bar v0.1.0+extra-stuff.0 -> v0.1.1+extra-stuff.1 + +"#]]) + .run(); + + Package::new("bar", "0.1.3").publish(); + p.cargo("update bar --precise 0.1.3+foo") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `bar` found +location searched: `dummy-registry` index (which is replacing registry `crates-io`) +required by package `foo v0.1.0 ([ROOT]/foo)` + +"#]]) + .run(); + + p.cargo("update bar --precise 0.1.3") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPDATING] bar v0.1.1+extra-stuff.1 -> v0.1.3 + +"#]]) + .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_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/rustdns` +[LOCKING] 1 package to latest compatible version + +"#]]) + .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_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[UPDATING] rootcrate v2.29.8 ([ROOT]/foo/rootcrate) -> v2.29.81 +[UPDATING] subcrate v2.29.8 ([ROOT]/foo/subcrate) -> v2.29.81 + +"#]]) + .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_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/rustdns` +[LOCKING] 1 package to latest compatible version + +"#]]) + .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_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[UPDATING] crate1 v2.29.8 ([ROOT]/foo/crate1) -> v2.29.81 +[UPDATING] crate2 v2.29.8 ([ROOT]/foo/crate2) -> v2.29.81 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_only_members_with_workspace() { + 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_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/rustdns` +[LOCKING] 1 package to latest compatible version + +"#]]) + .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 --workspace") + .with_stderr_data(str![[r#" +[LOCKING] 2 packages to latest compatible versions +[UPDATING] crate1 v2.29.8 ([ROOT]/foo/crate1) -> v2.29.81 +[UPDATING] crate2 v2.29.8 ([ROOT]/foo/crate2) -> v2.29.81 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_precise_git_revisions() { + let (git_project, git_repo) = git::new_repo("git", |p| { + p.file("Cargo.toml", &basic_lib_manifest("git")) + .file("src/lib.rs", "") + }); + let tag_name = "Nazgûl"; + git::tag(&git_repo, tag_name); + let tag_commit_id = git_repo.head().unwrap().target().unwrap().to_string(); + + git_project.change_file("src/lib.rs", "fn f() {}"); + git::add(&git_repo); + let head_id = git::commit(&git_repo).to_string(); + let short_id = &head_id[..8]; + let url = git_project.url(); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + git = {{ git = '{url}' }} + "# + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/git` +[LOCKING] 1 package to latest compatible version + +"#]]) + .run(); + + assert!(p.read_lockfile().contains(&head_id)); + + p.cargo("update git --precise") + .arg(tag_name) + .with_stderr_data(format!( + "\ +[UPDATING] git repository `[ROOTURL]/git` +[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{} +", + &tag_commit_id[..8], + )) + .run(); + + assert!(p.read_lockfile().contains(&tag_commit_id)); + assert!(!p.read_lockfile().contains(&head_id)); + + p.cargo("update git --precise") + .arg(short_id) + .with_stderr_data(format!( + "\ +[UPDATING] git repository `[ROOTURL]/git` +[UPDATING] git v0.5.0 ([ROOTURL]/git[..]) -> #{short_id} +", + )) + .run(); + + assert!(p.read_lockfile().contains(&head_id)); + assert!(!p.read_lockfile().contains(&tag_commit_id)); + + // updating back to tag still requires a git fetch, + // as the ref may change over time. + p.cargo("update git --precise") + .arg(tag_name) + .with_stderr_data(format!( + "\ +[UPDATING] git repository `[ROOTURL]/git` +[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{} +", + &tag_commit_id[..8], + )) + .run(); + + assert!(p.read_lockfile().contains(&tag_commit_id)); + assert!(!p.read_lockfile().contains(&head_id)); + + // Now make a tag looks like an oid. + // It requires a git fetch, as the oid cannot be found in preexisting git db. + let arbitrary_tag: String = std::iter::repeat('a').take(head_id.len()).collect(); + git::tag(&git_repo, &arbitrary_tag); + + p.cargo("update git --precise") + .arg(&arbitrary_tag) + .with_stderr_data(format!( + "\ +[UPDATING] git repository `[ROOTURL]/git` +[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{} +", + &head_id[..8], + )) + .run(); + + assert!(p.read_lockfile().contains(&head_id)); + assert!(!p.read_lockfile().contains(&tag_commit_id)); +} + +#[cargo_test] +fn precise_yanked() { + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.1").yanked(true).publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + + [dependencies] + bar = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + // Use non-yanked version. + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.0\"")); + + p.cargo("update --precise 0.1.1 bar") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] selected package `bar@0.1.1` was yanked by the author +[NOTE] if possible, try a compatible non-yanked version +[UPDATING] bar v0.1.0 -> v0.1.1 + +"#]]) + .run(); + + // Use yanked version. + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.1\"")); +} + +#[cargo_test] +fn precise_yanked_multiple_presence() { + Package::new("bar", "0.1.0").publish(); + Package::new("bar", "0.1.1").yanked(true).publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + + [dependencies] + bar = "0.1" + baz = { package = "bar", version = "0.1" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + // Use non-yanked version. + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.0\"")); + + p.cargo("update --precise 0.1.1 bar") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[WARNING] selected package `bar@0.1.1` was yanked by the author +[NOTE] if possible, try a compatible non-yanked version +[UPDATING] bar v0.1.0 -> v0.1.1 + +"#]]) + .run(); + + // Use yanked version. + let lockfile = p.read_lockfile(); + assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.1\"")); +} + +#[cargo_test] +fn report_behind() { + Package::new("two-ver", "0.1.0").publish(); + Package::new("two-ver", "0.2.0").publish(); + Package::new("pre", "1.0.0-alpha.0").publish(); + Package::new("pre", "1.0.0-alpha.1").publish(); + Package::new("breaking", "0.1.0").publish(); + Package::new("breaking", "0.2.0").publish(); + Package::new("breaking", "0.2.1-alpha.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + + [dependencies] + breaking = "0.1" + pre = "=1.0.0-alpha.0" + two-ver = "0.2.0" + two-ver-one = { version = "0.1.0", package = "two-ver" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + Package::new("breaking", "0.1.1").publish(); + + p.cargo("update --dry-run") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] breaking v0.1.0 -> v0.1.1 (available: v0.2.0) +[NOTE] pass `--verbose` to see 2 unchanged dependencies behind latest +[WARNING] not updating lockfile due to dry run + +"#]]) + .run(); + + p.cargo("update --dry-run --verbose") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] breaking v0.1.0 -> v0.1.1 (available: v0.2.0) +[UNCHANGED] pre v1.0.0-alpha.0 (available: v1.0.0-alpha.1) +[UNCHANGED] two-ver v0.1.0 (available: v0.2.0) +[NOTE] to see how you depend on a package, run `cargo tree --invert --package @` +[WARNING] not updating lockfile due to dry run + +"#]]) + .run(); + + p.cargo("update").run(); + + p.cargo("update --dry-run") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 0 packages to latest compatible versions +[NOTE] pass `--verbose` to see 3 unchanged dependencies behind latest +[WARNING] not updating lockfile due to dry run + +"#]]) + .run(); + + p.cargo("update --dry-run --verbose") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 0 packages to latest compatible versions +[UNCHANGED] breaking v0.1.1 (available: v0.2.0) +[UNCHANGED] pre v1.0.0-alpha.0 (available: v1.0.0-alpha.1) +[UNCHANGED] two-ver v0.1.0 (available: v0.2.0) +[NOTE] to see how you depend on a package, run `cargo tree --invert --package @` +[WARNING] not updating lockfile due to dry run + +"#]]) + .run(); +} + +#[cargo_test] +fn update_with_missing_feature() { + // Attempting to update a package to a version with a missing feature + // should produce a warning. + Package::new("bar", "0.1.0").feature("feat1", &[]).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = {version="0.1", features=["feat1"]} + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("generate-lockfile").run(); + + // Publish an update that is missing the feature. + Package::new("bar", "0.1.1").publish(); + + p.cargo("update") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 0 packages to latest compatible versions +[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest + +"#]]) + .run(); + + // Publish a fixed version, should not warn. + Package::new("bar", "0.1.2").feature("feat1", &[]).publish(); + p.cargo("update") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v0.1.0 -> v0.1.2 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_unstable() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("update --breaking") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] the `--breaking` flag is unstable, pass `-Z unstable-options` to enable it +See https://github.com/rust-lang/cargo/issues/12425 for more information about the `--breaking` flag. + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_dry_run() { + Package::new("incompatible", "1.0.0").publish(); + Package::new("ws", "1.0.0").publish(); + + let root_manifest = r#" + # Check if formatting is preserved. Nothing here should change, due to dry-run. + + [workspace] + members = ["foo"] + + [workspace.dependencies] + ws = "1.0" # Preserve formatting + "#; + + let crate_manifest = r#" + # Check if formatting is preserved. Nothing here should change, due to dry-run. + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + incompatible = "1.0" # Preserve formatting + ws.workspace = true # Preserve formatting + "#; + + let p = project() + .file("Cargo.toml", root_manifest) + .file("foo/Cargo.toml", crate_manifest) + .file("foo/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + let lock_file = p.read_file("Cargo.lock"); + + Package::new("incompatible", "1.0.1").publish(); + Package::new("ws", "1.0.1").publish(); + + Package::new("incompatible", "2.0.0").publish(); + Package::new("ws", "2.0.0").publish(); + + p.cargo("update -Zunstable-options --dry-run --breaking") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPGRADING] incompatible ^1.0 -> ^2.0 +[UPGRADING] ws ^1.0 -> ^2.0 +[LOCKING] 2 packages to latest compatible versions +[UPDATING] incompatible v1.0.0 -> v2.0.0 +[UPDATING] ws v1.0.0 -> v2.0.0 +[WARNING] aborting update due to dry run + +"#]]) + .run(); + + let root_manifest_after = p.read_file("Cargo.toml"); + assert_e2e().eq(&root_manifest_after, root_manifest); + + let crate_manifest_after = p.read_file("foo/Cargo.toml"); + assert_e2e().eq(&crate_manifest_after, crate_manifest); + + let lock_file_after = p.read_file("Cargo.lock"); + assert_e2e().eq(&lock_file_after, lock_file); +} + +#[cargo_test] +fn update_breaking() { + registry::alt_init(); + Package::new("compatible", "1.0.0").publish(); + Package::new("incompatible", "1.0.0").publish(); + Package::new("pinned", "1.0.0").publish(); + Package::new("less-than", "1.0.0").publish(); + Package::new("renamed-from", "1.0.0").publish(); + Package::new("pre-release", "1.0.0").publish(); + Package::new("yanked", "1.0.0").publish(); + Package::new("ws", "1.0.0").publish(); + Package::new("shared", "1.0.0").publish(); + Package::new("multiple-locations", "1.0.0").publish(); + Package::new("multiple-versions", "1.0.0").publish(); + Package::new("multiple-versions", "2.0.0").publish(); + Package::new("alternative-1", "1.0.0") + .alternative(true) + .publish(); + Package::new("alternative-2", "1.0.0") + .alternative(true) + .publish(); + Package::new("bar", "1.0.0").alternative(true).publish(); + Package::new("multiple-registries", "1.0.0").publish(); + Package::new("multiple-registries", "2.0.0") + .alternative(true) + .publish(); + Package::new("multiple-source-types", "1.0.0").publish(); + Package::new("platform-specific", "1.0.0").publish(); + Package::new("dev", "1.0.0").publish(); + Package::new("build", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + # Check if formatting is preserved + + [workspace] + members = ["foo", "bar"] + + [workspace.dependencies] + ws = "1.0" # This line gets partially rewritten + "#, + ) + .file( + "foo/Cargo.toml", + r#" + # Check if formatting is preserved + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + compatible = "1.0" # Comment + incompatible = "1.0" # Comment + pinned = "=1.0" # Comment + less-than = "<99.0" # Comment + renamed-to = { package = "renamed-from", version = "1.0" } # Comment + pre-release = "1.0" # Comment + yanked = "1.0" # Comment + ws.workspace = true # Comment + shared = "1.0" # Comment + multiple-locations = { path = "../multiple-locations", version = "1.0" } # Comment + multiple-versions = "1.0" # Comment + alternative-1 = { registry = "alternative", version = "1.0" } # Comment + multiple-registries = "1.0" # Comment + bar = { path = "../bar", registry = "alternative", version = "1.0.0" } # Comment + multiple-source-types = { path = "../multiple-source-types", version = "1.0.0" } # Comment + + [dependencies.alternative-2] # Comment + version = "1.0" # Comment + registry = "alternative" # Comment + + [target.'cfg(unix)'.dependencies] + platform-specific = "1.0" # Comment + + [dev-dependencies] + dev = "1.0" # Comment + + [build-dependencies] + build = "1.0" # Comment + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "1.0.0" + edition = "2015" + authors = [] + + [dependencies] + shared = "1.0" + multiple-versions = "2.0" + multiple-registries = { registry = "alternative", version = "2.0" } # Comment + multiple-source-types = "1.0" # Comment + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "multiple-locations/Cargo.toml", + r#" + [package] + name = "multiple-locations" + version = "1.0.0" + edition = "2015" + authors = [] + "#, + ) + .file("multiple-locations/src/lib.rs", "") + .file( + "multiple-source-types/Cargo.toml", + r#" + [package] + name = "multiple-source-types" + version = "1.0.0" + edition = "2015" + authors = [] + "#, + ) + .file("multiple-source-types/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + Package::new("compatible", "1.0.1").publish(); + Package::new("incompatible", "1.0.1").publish(); + Package::new("pinned", "1.0.1").publish(); + Package::new("less-than", "1.0.1").publish(); + Package::new("renamed-from", "1.0.1").publish(); + Package::new("ws", "1.0.1").publish(); + Package::new("multiple-locations", "1.0.1").publish(); + Package::new("multiple-versions", "1.0.1").publish(); + Package::new("multiple-versions", "2.0.1").publish(); + Package::new("alternative-1", "1.0.1") + .alternative(true) + .publish(); + Package::new("alternative-2", "1.0.1") + .alternative(true) + .publish(); + Package::new("platform-specific", "1.0.1").publish(); + Package::new("dev", "1.0.1").publish(); + Package::new("build", "1.0.1").publish(); + + Package::new("incompatible", "2.0.0").publish(); + Package::new("pinned", "2.0.0").publish(); + Package::new("less-than", "2.0.0").publish(); + Package::new("renamed-from", "2.0.0").publish(); + Package::new("pre-release", "2.0.0-alpha").publish(); + Package::new("yanked", "2.0.0").yanked(true).publish(); + Package::new("ws", "2.0.0").publish(); + Package::new("shared", "2.0.0").publish(); + Package::new("multiple-locations", "2.0.0").publish(); + Package::new("multiple-versions", "3.0.0").publish(); + Package::new("alternative-1", "2.0.0") + .alternative(true) + .publish(); + Package::new("alternative-2", "2.0.0") + .alternative(true) + .publish(); + Package::new("bar", "2.0.0").alternative(true).publish(); + Package::new("multiple-registries", "2.0.0").publish(); + Package::new("multiple-registries", "3.0.0") + .alternative(true) + .publish(); + Package::new("multiple-source-types", "2.0.0").publish(); + Package::new("platform-specific", "2.0.0").publish(); + Package::new("dev", "2.0.0").publish(); + Package::new("build", "2.0.0").publish(); + + p.cargo("update -Zunstable-options --breaking") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[UPGRADING] multiple-registries ^2.0 -> ^3.0 +[UPDATING] `dummy-registry` index +[UPGRADING] multiple-source-types ^1.0 -> ^2.0 +[UPGRADING] multiple-versions ^2.0 -> ^3.0 +[UPGRADING] shared ^1.0 -> ^2.0 +[UPGRADING] alternative-1 ^1.0 -> ^2.0 +[UPGRADING] alternative-2 ^1.0 -> ^2.0 +[UPGRADING] incompatible ^1.0 -> ^2.0 +[UPGRADING] multiple-registries ^1.0 -> ^2.0 +[UPGRADING] multiple-versions ^1.0 -> ^3.0 +[UPGRADING] ws ^1.0 -> ^2.0 +[UPGRADING] dev ^1.0 -> ^2.0 +[UPGRADING] build ^1.0 -> ^2.0 +[UPGRADING] platform-specific ^1.0 -> ^2.0 +[LOCKING] 12 packages to latest compatible versions +[UPDATING] alternative-1 v1.0.0 (registry `alternative`) -> v2.0.0 +[UPDATING] alternative-2 v1.0.0 (registry `alternative`) -> v2.0.0 +[UPDATING] build v1.0.0 -> v2.0.0 +[UPDATING] dev v1.0.0 -> v2.0.0 +[UPDATING] incompatible v1.0.0 -> v2.0.0 +[UPDATING] multiple-registries v2.0.0 (registry `alternative`) -> v3.0.0 +[UPDATING] multiple-registries v1.0.0 -> v2.0.0 +[UPDATING] multiple-source-types v1.0.0 -> v2.0.0 +[ADDING] multiple-versions v3.0.0 +[UPDATING] platform-specific v1.0.0 -> v2.0.0 +[UPDATING] shared v1.0.0 -> v2.0.0 +[UPDATING] ws v1.0.0 -> v2.0.0 + +"#]]) + .run(); + + let root_manifest = p.read_file("Cargo.toml"); + assert_e2e().eq( + &root_manifest, + str![[r#" + + # Check if formatting is preserved + + [workspace] + members = ["foo", "bar"] + + [workspace.dependencies] + ws = "2.0" # This line gets partially rewritten + "#]], + ); + + let foo_manifest = p.read_file("foo/Cargo.toml"); + + assert_e2e().eq( + &foo_manifest, + str![[r#" + + # Check if formatting is preserved + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + compatible = "1.0" # Comment + incompatible = "2.0" # Comment + pinned = "=1.0" # Comment + less-than = "<99.0" # Comment + renamed-to = { package = "renamed-from", version = "1.0" } # Comment + pre-release = "1.0" # Comment + yanked = "1.0" # Comment + ws.workspace = true # Comment + shared = "2.0" # Comment + multiple-locations = { path = "../multiple-locations", version = "1.0" } # Comment + multiple-versions = "3.0" # Comment + alternative-1 = { registry = "alternative", version = "2.0" } # Comment + multiple-registries = "2.0" # Comment + bar = { path = "../bar", registry = "alternative", version = "1.0.0" } # Comment + multiple-source-types = { path = "../multiple-source-types", version = "1.0.0" } # Comment + + [dependencies.alternative-2] # Comment + version = "2.0" # Comment + registry = "alternative" # Comment + + [target.'cfg(unix)'.dependencies] + platform-specific = "2.0" # Comment + + [dev-dependencies] + dev = "2.0" # Comment + + [build-dependencies] + build = "2.0" # Comment + "#]], + ); + + let bar_manifest = p.read_file("bar/Cargo.toml"); + + assert_e2e().eq( + &bar_manifest, + str![[r#" + + [package] + name = "bar" + version = "1.0.0" + edition = "2015" + authors = [] + + [dependencies] + shared = "2.0" + multiple-versions = "3.0" + multiple-registries = { registry = "alternative", version = "3.0" } # Comment + multiple-source-types = "2.0" # Comment + "#]], + ); + + p.cargo("update") + .with_stderr_data(str![[r#" +[UPDATING] `alternative` index +[UPDATING] `dummy-registry` index +[LOCKING] 4 packages to latest compatible versions +[UPDATING] compatible v1.0.0 -> v1.0.1 +[UPDATING] less-than v1.0.0 -> v2.0.0 +[UPDATING] pinned v1.0.0 -> v1.0.1 (available: v2.0.0) +[UPDATING] renamed-from v1.0.0 -> v1.0.1 (available: v2.0.0) + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_specific_packages() { + Package::new("just-foo", "1.0.0") + .add_dep(Dependency::new("transitive-compatible", "1.0.0").build()) + .add_dep(Dependency::new("transitive-incompatible", "1.0.0").build()) + .publish(); + Package::new("just-bar", "1.0.0").publish(); + Package::new("shared", "1.0.0").publish(); + Package::new("ws", "1.0.0").publish(); + Package::new("transitive-compatible", "1.0.0").publish(); + Package::new("transitive-incompatible", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + + [workspace.dependencies] + ws = "1.0" + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + just-foo = "1.0" + shared = "1.0" + ws.workspace = true + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + just-bar = "1.0" + shared = "1.0" + ws.workspace = true + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + Package::new("just-foo", "1.0.1") + .add_dep(Dependency::new("transitive-compatible", "1.0.0").build()) + .add_dep(Dependency::new("transitive-incompatible", "1.0.0").build()) + .publish(); + Package::new("just-bar", "1.0.1").publish(); + Package::new("shared", "1.0.1").publish(); + Package::new("ws", "1.0.1").publish(); + Package::new("transitive-compatible", "1.0.1").publish(); + Package::new("transitive-incompatible", "1.0.1").publish(); + + Package::new("just-foo", "2.0.0") + // Upgrading just-foo implies accepting an update of transitive-compatible. + .add_dep(Dependency::new("transitive-compatible", "1.0.1").build()) + // Upgrading just-foo implies accepting a major update of transitive-incompatible. + .add_dep(Dependency::new("transitive-incompatible", "2.0.0").build()) + .publish(); + Package::new("just-bar", "2.0.0").publish(); + Package::new("shared", "2.0.0").publish(); + Package::new("ws", "2.0.0").publish(); + Package::new("transitive-incompatible", "2.0.0").publish(); + + p.cargo("update -Zunstable-options --breaking just-foo shared ws") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPGRADING] shared ^1.0 -> ^2.0 +[UPGRADING] ws ^1.0 -> ^2.0 +[UPGRADING] just-foo ^1.0 -> ^2.0 +[LOCKING] 5 packages to latest compatible versions +[UPDATING] just-foo v1.0.0 -> v2.0.0 +[UPDATING] shared v1.0.0 -> v2.0.0 +[UPDATING] transitive-compatible v1.0.0 -> v1.0.1 +[UPDATING] transitive-incompatible v1.0.0 -> v2.0.0 +[UPDATING] ws v1.0.0 -> v2.0.0 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_specific_packages_that_wont_update() { + Package::new("compatible", "1.0.0").publish(); + Package::new("renamed-from", "1.0.0").publish(); + Package::new("non-semver", "1.0.0").publish(); + Package::new("bar", "1.0.0") + .add_dep(Dependency::new("transitive-compatible", "1.0.0").build()) + .add_dep(Dependency::new("transitive-incompatible", "1.0.0").build()) + .publish(); + Package::new("transitive-compatible", "1.0.0").publish(); + Package::new("transitive-incompatible", "1.0.0").publish(); + + let crate_manifest = r#" + # Check if formatting is preserved + + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + compatible = "1.0" # Comment + renamed-to = { package = "renamed-from", version = "1.0" } # Comment + non-semver = "~1.0" # Comment + bar = "1.0" # Comment + "#; + + let p = project() + .file("Cargo.toml", crate_manifest) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + let lock_file = p.read_file("Cargo.lock"); + + Package::new("compatible", "1.0.1").publish(); + Package::new("renamed-from", "1.0.1").publish(); + Package::new("non-semver", "1.0.1").publish(); + Package::new("transitive-compatible", "1.0.1").publish(); + Package::new("transitive-incompatible", "1.0.1").publish(); + + Package::new("renamed-from", "2.0.0").publish(); + Package::new("non-semver", "2.0.0").publish(); + Package::new("transitive-incompatible", "2.0.0").publish(); + + p.cargo("update -Zunstable-options --breaking compatible renamed-from non-semver transitive-compatible transitive-incompatible") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index + +"#]]) + .run(); + + let crate_manifest_after = p.read_file("Cargo.toml"); + assert_e2e().eq(&crate_manifest_after, crate_manifest); + + let lock_file_after = p.read_file("Cargo.lock"); + assert_e2e().eq(&lock_file_after, lock_file); + + p.cargo( + "update compatible renamed-from non-semver transitive-compatible transitive-incompatible", + ) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[LOCKING] 5 packages to latest compatible versions +[UPDATING] compatible v1.0.0 -> v1.0.1 +[UPDATING] non-semver v1.0.0 -> v1.0.1 (available: v2.0.0) +[UPDATING] renamed-from v1.0.0 -> v1.0.1 (available: v2.0.0) +[UPDATING] transitive-compatible v1.0.0 -> v1.0.1 +[UPDATING] transitive-incompatible v1.0.0 -> v1.0.1 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_without_lock_file() { + Package::new("compatible", "1.0.0").publish(); + Package::new("incompatible", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + compatible = "1.0" # Comment + incompatible = "1.0" # Comment + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("compatible", "1.0.1").publish(); + Package::new("incompatible", "1.0.1").publish(); + + Package::new("incompatible", "2.0.0").publish(); + + p.cargo("update -Zunstable-options --breaking") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[UPGRADING] incompatible ^1.0 -> ^2.0 +[LOCKING] 2 packages to latest compatible versions + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_spec_version() { + Package::new("compatible", "1.0.0").publish(); + Package::new("incompatible", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + compatible = "1.0" # Comment + incompatible = "1.0" # Comment + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + Package::new("compatible", "1.0.1").publish(); + Package::new("incompatible", "1.0.1").publish(); + + Package::new("incompatible", "2.0.0").publish(); + + // Invalid spec + p.cargo("update -Zunstable-options --breaking incompatible@foo") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] invalid package ID specification: `incompatible@foo` + +Caused by: + expected a version like "1.32" + +"#]]) + .run(); + + // Spec version not matching our current dependencies + p.cargo("update -Zunstable-options --breaking incompatible@2.0.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#""#]]) + .run(); + + // Spec source not matching our current dependencies + p.cargo("update -Zunstable-options --breaking https://alternative.com#incompatible@1.0.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#""#]]) + .run(); + + // Accepted spec + p.cargo("update -Zunstable-options --breaking incompatible@1.0.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[UPGRADING] incompatible ^1.0 -> ^2.0 +[LOCKING] 1 package to latest compatible version +[UPDATING] incompatible v1.0.0 -> v2.0.0 + +"#]]) + .run(); + + // Accepted spec, full format + Package::new("incompatible", "3.0.0").publish(); + p.cargo("update -Zunstable-options --breaking https://github.com/rust-lang/crates.io-index#incompatible@2.0.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[UPGRADING] incompatible ^2.0 -> ^3.0 +[LOCKING] 1 package to latest compatible version +[UPDATING] incompatible v2.0.0 -> v3.0.0 + +"#]]) + .run(); + + // Spec matches a dependency that will not be upgraded + p.cargo("update -Zunstable-options --breaking compatible@1.0.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index + +"#]]) + .run(); + + // Non-existing versions + p.cargo("update -Zunstable-options --breaking incompatible@9.0.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#""#]]) + .run(); + + p.cargo("update -Zunstable-options --breaking compatible@9.0.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#""#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_spec_version_transitive() { + Package::new("dep", "1.0.0").publish(); + Package::new("dep", "1.1.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + dep = "1.0" + bar = { path = "bar", version = "0.0.1" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + dep = "1.1" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + Package::new("dep", "1.1.1").publish(); + Package::new("dep", "2.0.0").publish(); + + // Will upgrade the direct dependency + p.cargo("update -Zunstable-options --breaking dep@1.0") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[UPGRADING] dep ^1.0 -> ^2.0 +[LOCKING] 1 package to latest compatible version +[ADDING] dep v2.0.0 + +"#]]) + .run(); + + // But not the transitive one, because bar is not a workspace member + p.cargo("update -Zunstable-options --breaking dep@1.1") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index + +"#]]) + .run(); + + // A non-breaking update is different, as it will update transitive dependencies + p.cargo("update dep@1.1") + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[LOCKING] 1 package to latest compatible version +[UPDATING] dep v1.1.0 -> v1.1.1 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_mixed_compatibility() { + Package::new("mixed-compatibility", "1.0.0").publish(); + Package::new("mixed-compatibility", "2.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + mixed-compatibility = "1.0" + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + mixed-compatibility = "2.0" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + Package::new("mixed-compatibility", "2.0.1").publish(); + + p.cargo("update -Zunstable-options --breaking") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[UPGRADING] mixed-compatibility ^1.0 -> ^2.0 +[LOCKING] 1 package to latest compatible version +[ADDING] mixed-compatibility v2.0.1 + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_mixed_pinning_renaming() { + Package::new("mixed-pinned", "1.0.0").publish(); + Package::new("mixed-ws-pinned", "1.0.0").publish(); + Package::new("renamed-from", "1.0.0").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["pinned", "unpinned", "mixed"] + + [workspace.dependencies] + mixed-ws-pinned = "=1.0" + "#, + ) + .file( + "pinned/Cargo.toml", + r#" + [package] + name = "pinned" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + mixed-pinned = "=1.0" + mixed-ws-pinned.workspace = true + renamed-to = { package = "renamed-from", version = "1.0" } + "#, + ) + .file("pinned/src/lib.rs", "") + .file( + "unpinned/Cargo.toml", + r#" + [package] + name = "unpinned" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + mixed-pinned = "1.0" + mixed-ws-pinned = "1.0" + renamed-from = "1.0" + "#, + ) + .file("unpinned/src/lib.rs", "") + .file( + "mixed/Cargo.toml", + r#" + [package] + name = "mixed" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(windows)'.dependencies] + mixed-pinned = "1.0" + + [target.'cfg(unix)'.dependencies] + mixed-pinned = "=1.0" + "#, + ) + .file("mixed/src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + Package::new("mixed-pinned", "2.0.0").publish(); + Package::new("mixed-ws-pinned", "2.0.0").publish(); + Package::new("renamed-from", "2.0.0").publish(); + + p.cargo("update -Zunstable-options --breaking") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `[..]` index +[UPGRADING] mixed-pinned ^1.0 -> ^2.0 +[UPGRADING] mixed-ws-pinned ^1.0 -> ^2.0 +[UPGRADING] renamed-from ^1.0 -> ^2.0 +[LOCKING] 3 packages to latest compatible versions +[ADDING] mixed-pinned v2.0.0 +[ADDING] mixed-ws-pinned v2.0.0 +[ADDING] renamed-from v2.0.0 + +"#]]) + .run(); + + let root_manifest = p.read_file("Cargo.toml"); + assert_e2e().eq( + &root_manifest, + str![[r#" + + [workspace] + members = ["pinned", "unpinned", "mixed"] + + [workspace.dependencies] + mixed-ws-pinned = "=1.0" + "#]], + ); + + let pinned_manifest = p.read_file("pinned/Cargo.toml"); + assert_e2e().eq( + &pinned_manifest, + str![[r#" + + [package] + name = "pinned" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + mixed-pinned = "=1.0" + mixed-ws-pinned.workspace = true + renamed-to = { package = "renamed-from", version = "1.0" } + "#]], + ); + + let unpinned_manifest = p.read_file("unpinned/Cargo.toml"); + assert_e2e().eq( + &unpinned_manifest, + str![[r#" + + [package] + name = "unpinned" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + mixed-pinned = "2.0" + mixed-ws-pinned = "2.0" + renamed-from = "2.0" + "#]], + ); + + let mixed_manifest = p.read_file("mixed/Cargo.toml"); + assert_e2e().eq( + &mixed_manifest, + str![[r#" + + [package] + name = "mixed" + version = "0.0.1" + edition = "2015" + authors = [] + + [target.'cfg(windows)'.dependencies] + mixed-pinned = "2.0" + + [target.'cfg(unix)'.dependencies] + mixed-pinned = "=1.0" + "#]], + ); +} + +#[cargo_test] +fn update_breaking_pre_release_downgrade() { + Package::new("bar", "2.0.0-beta.21").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "2.0.0-beta.21" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + // The purpose of this test is + // to demonstrate that `update --breaking` will not try to downgrade to the latest stable version (1.7.0), + // but will rather keep the latest pre-release (2.0.0-beta.21). + Package::new("bar", "1.7.0").publish(); + p.cargo("update -Zunstable-options --breaking bar") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index + +"#]]) + .run(); +} + +#[cargo_test] +fn update_breaking_pre_release_upgrade() { + Package::new("bar", "2.0.0-beta.21").publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "2.0.0-beta.21" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile").run(); + + // TODO: `2.0.0-beta.21` can be upgraded to `2.0.0-beta.22` + Package::new("bar", "2.0.0-beta.22").publish(); + p.cargo("update -Zunstable-options --breaking bar") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index + +"#]]) + .run(); + // TODO: `2.0.0-beta.21` can be upgraded to `2.0.0` + Package::new("bar", "2.0.0").publish(); + p.cargo("update -Zunstable-options --breaking bar") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index + +"#]]) + .run(); + + Package::new("bar", "3.0.0").publish(); + p.cargo("update -Zunstable-options --breaking bar") + .masquerade_as_nightly_cargo(&["update-breaking"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[UPGRADING] bar ^2.0.0-beta.21 -> ^3.0.0 +[LOCKING] 1 package to latest compatible version +[UPDATING] bar v2.0.0-beta.21 -> v3.0.0 + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/vendor.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/vendor.rs new file mode 100644 index 000000000..7ea31b5b5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/vendor.rs @@ -0,0 +1,1941 @@ +//! Tests for the `cargo vendor` command. +//! +//! Note that every test here uses `--respect-source-config` so that the +//! "fake" crates.io is used. Otherwise `vendor` would download the crates.io +//! index from the network. + +use std::fs; + +use cargo_test_support::compare::assert_e2e; +use cargo_test_support::git; +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{self, Package, RegistryBuilder}; +use cargo_test_support::str; +use cargo_test_support::{basic_lib_manifest, basic_manifest, paths, project, Project}; + +#[cargo_test] +fn vendor_simple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + log = "0.3.5" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("log", "0.3.5").publish(); + + p.cargo("vendor --respect-source-config").run(); + let lock = p.read_file("vendor/log/Cargo.toml"); + assert!(lock.contains("version = \"0.3.5\"")); + + add_crates_io_vendor_config(&p); + p.cargo("check").run(); +} + +#[cargo_test] +fn vendor_sample_config() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + log = "0.3.5" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("log", "0.3.5").publish(); + + p.cargo("vendor --respect-source-config") + .with_stdout_data(str![[r#" +[source.crates-io] +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "vendor" + +"#]]) + .run(); +} + +#[cargo_test] +fn vendor_sample_config_alt_registry() { + let registry = RegistryBuilder::new().alternative().http_index().build(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + log = { version = "0.3.5", registry = "alternative" } + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("log", "0.3.5").alternative(true).publish(); + + p.cargo("vendor --respect-source-config") + .with_stdout_data(format!( + r#"[source."{0}"] +registry = "{0}" +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "vendor" +"#, + registry.index_url() + )) + .run(); +} + +#[cargo_test] +fn vendor_path_specified() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + log = "0.3.5" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("log", "0.3.5").publish(); + + let path = if cfg!(windows) { + r#"deps\.vendor"# + } else { + "deps/.vendor" + }; + + let output = p.cargo("vendor --respect-source-config").arg(path).run(); + // Assert against original output to ensure that + // path is normalized by `ops::vendor` on Windows. + assert_eq!( + &String::from_utf8(output.stdout).unwrap(), + r#"[source.crates-io] +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "deps/.vendor" +"# + ); + + let lock = p.read_file("deps/.vendor/log/Cargo.toml"); + assert!(lock.contains("version = \"0.3.5\"")); +} + +fn add_crates_io_vendor_config(p: &Project) { + p.change_file( + ".cargo/config.toml", + r#" + [source.crates-io] + replace-with = 'vendor' + + [source.vendor] + directory = 'vendor' + "#, + ); +} + +fn add_git_vendor_config(p: &Project, git_project: &Project) { + p.change_file( + ".cargo/config.toml", + &format!( + r#" + [source."git+{url}"] + git = "{url}" + replace-with = 'vendor' + + [source.vendor] + directory = 'vendor' + "#, + url = git_project.url() + ), + ); +} + +#[cargo_test] +fn package_exclude() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("bar", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + exclude = [".*", "!.include", "!.dotdir/include"] + "#, + ) + .file("src/lib.rs", "") + .file(".exclude", "") + .file(".include", "") + .file(".dotdir/exclude", "") + .file(".dotdir/include", "") + .publish(); + + p.cargo("vendor --respect-source-config").run(); + let csum = p.read_file("vendor/bar/.cargo-checksum.json"); + assert!(csum.contains(".include")); + assert!(!csum.contains(".exclude")); + assert!(!csum.contains(".dotdir/exclude")); + // Gitignore doesn't re-include a file in an excluded parent directory, + // even if negating it explicitly. + assert!(!csum.contains(".dotdir/include")); +} + +#[cargo_test] +fn discovery_inferred_build_rs_included() { + let git_project = git::new("dep", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "dep" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs", "build.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("vendor --respect-source-config").run(); + add_git_vendor_config(&p, &git_project); + + let lock = p.read_file("vendor/dep/Cargo.toml"); + assert_e2e().eq( + lock, + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "dep" +version = "0.0.1" +authors = [] +build = "build.rs" +include = [ + "src/lib.rs", + "build.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "dep" +path = "src/lib.rs" + +"##]], + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn discovery_inferred_build_rs_excluded() { + let git_project = git::new("dep", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "dep" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("build.rs", "fn main() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("vendor --respect-source-config").run(); + add_git_vendor_config(&p, &git_project); + + let lock = p.read_file("vendor/dep/Cargo.toml"); + assert_e2e().eq( + lock, + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "dep" +version = "0.0.1" +authors = [] +build = false +include = ["src/lib.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "dep" +path = "src/lib.rs" + +"##]], + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn discovery_inferred_lib_included() { + let git_project = git::new("dep", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "dep" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/main.rs", "src/lib.rs"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("vendor --respect-source-config").run(); + add_git_vendor_config(&p, &git_project); + + let lock = p.read_file("vendor/dep/Cargo.toml"); + assert_e2e().eq( + lock, + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "dep" +version = "0.0.1" +authors = [] +build = false +include = [ + "src/main.rs", + "src/lib.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "dep" +path = "src/lib.rs" + +[[bin]] +name = "dep" +path = "src/main.rs" + +"##]], + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn discovery_inferred_lib_excluded() { + let git_project = git::new("dep", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "dep" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/main.rs"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("vendor --respect-source-config").run(); + add_git_vendor_config(&p, &git_project); + + let lock = p.read_file("vendor/dep/Cargo.toml"); + assert_e2e().eq( + lock, + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "dep" +version = "0.0.1" +authors = [] +build = false +include = ["src/main.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[[bin]] +name = "dep" +path = "src/main.rs" + +"##]], + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn discovery_inferred_other_included() { + let git_project = git::new("dep", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "dep" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs", "src/bin/foo/main.rs", "examples/example_foo.rs", "tests/test_foo.rs", "benches/bench_foo.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/foo/main.rs", "fn main() {}") + .file("examples/example_foo.rs", "fn main() {}") + .file("tests/test_foo.rs", "fn main() {}") + .file("benches/bench_foo.rs", "fn main() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("vendor --respect-source-config").run(); + add_git_vendor_config(&p, &git_project); + + let lock = p.read_file("vendor/dep/Cargo.toml"); + assert_e2e().eq( + lock, + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "dep" +version = "0.0.1" +authors = [] +build = false +include = [ + "src/lib.rs", + "src/bin/foo/main.rs", + "examples/example_foo.rs", + "tests/test_foo.rs", + "benches/bench_foo.rs", +] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "dep" +path = "src/lib.rs" + +[[bin]] +name = "foo" +path = "src/bin/foo/main.rs" + +[[example]] +name = "example_foo" +path = "examples/example_foo.rs" + +[[test]] +name = "test_foo" +path = "tests/test_foo.rs" + +[[bench]] +name = "bench_foo" +path = "benches/bench_foo.rs" + +"##]], + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn discovery_inferred_other_excluded() { + let git_project = git::new("dep", |project| { + project + .file( + "Cargo.toml", + r#" + [package] + name = "dep" + version = "0.0.1" + edition = "2015" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + include = ["src/lib.rs"] + "#, + ) + .file("src/lib.rs", "") + .file("src/bin/foo/main.rs", "fn main() {}") + .file("examples/example_foo.rs", "fn main() {}") + .file("tests/test_foo.rs", "fn main() {}") + .file("benches/bench_foo.rs", "fn main() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + + [dependencies.dep] + git = '{}' + "#, + git_project.url() + ), + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("vendor --respect-source-config").run(); + add_git_vendor_config(&p, &git_project); + + let lock = p.read_file("vendor/dep/Cargo.toml"); + assert_e2e().eq( + lock, + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "dep" +version = "0.0.1" +authors = [] +build = false +include = ["src/lib.rs"] +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "dep" +path = "src/lib.rs" + +"##]], + ); + + p.cargo("check").run(); +} + +#[cargo_test] +fn two_versions() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bitflags = "0.8.0" + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + + [dependencies] + bitflags = "0.7.0" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + Package::new("bitflags", "0.7.0").publish(); + Package::new("bitflags", "0.8.0").publish(); + + p.cargo("vendor --respect-source-config").run(); + + let lock = p.read_file("vendor/bitflags/Cargo.toml"); + assert!(lock.contains("version = \"0.8.0\"")); + let lock = p.read_file("vendor/bitflags-0.7.0/Cargo.toml"); + assert!(lock.contains("version = \"0.7.0\"")); + + add_crates_io_vendor_config(&p); + p.cargo("check").run(); +} + +#[cargo_test] +fn two_explicit_versions() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bitflags = "0.8.0" + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + + [dependencies] + bitflags = "0.7.0" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + Package::new("bitflags", "0.7.0").publish(); + Package::new("bitflags", "0.8.0").publish(); + + p.cargo("vendor --respect-source-config --versioned-dirs") + .run(); + + let lock = p.read_file("vendor/bitflags-0.8.0/Cargo.toml"); + assert!(lock.contains("version = \"0.8.0\"")); + let lock = p.read_file("vendor/bitflags-0.7.0/Cargo.toml"); + assert!(lock.contains("version = \"0.7.0\"")); + + add_crates_io_vendor_config(&p); + p.cargo("check").run(); +} + +#[cargo_test] +fn help() { + let p = project().build(); + p.cargo("vendor -h").run(); +} + +#[cargo_test] +fn update_versions() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bitflags = "0.7.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("bitflags", "0.7.0").publish(); + Package::new("bitflags", "0.8.0").publish(); + + p.cargo("vendor --respect-source-config").run(); + + let lock = p.read_file("vendor/bitflags/Cargo.toml"); + assert!(lock.contains("version = \"0.7.0\"")); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bitflags = "0.8.0" + "#, + ); + p.cargo("vendor --respect-source-config").run(); + + let lock = p.read_file("vendor/bitflags/Cargo.toml"); + assert!(lock.contains("version = \"0.8.0\"")); +} + +#[cargo_test] +fn two_lockfiles() { + let p = project() + .no_manifest() + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bitflags = "=0.7.0" + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + + [dependencies] + bitflags = "=0.8.0" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + Package::new("bitflags", "0.7.0").publish(); + Package::new("bitflags", "0.8.0").publish(); + + p.cargo("vendor --respect-source-config -s bar/Cargo.toml --manifest-path foo/Cargo.toml") + .run(); + + let lock = p.read_file("vendor/bitflags/Cargo.toml"); + assert!(lock.contains("version = \"0.8.0\"")); + let lock = p.read_file("vendor/bitflags-0.7.0/Cargo.toml"); + assert!(lock.contains("version = \"0.7.0\"")); + + add_crates_io_vendor_config(&p); + p.cargo("check").cwd("foo").run(); + p.cargo("check").cwd("bar").run(); +} + +#[cargo_test] +fn test_sync_argument() { + let p = project() + .no_manifest() + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bitflags = "=0.7.0" + "#, + ) + .file("foo/src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + + [dependencies] + bitflags = "=0.8.0" + "#, + ) + .file("bar/src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + + [dependencies] + bitflags = "=0.8.0" + "#, + ) + .file("baz/src/lib.rs", "") + .build(); + + Package::new("bitflags", "0.7.0").publish(); + Package::new("bitflags", "0.8.0").publish(); + + p.cargo("vendor --respect-source-config --manifest-path foo/Cargo.toml -s bar/Cargo.toml baz/Cargo.toml test_vendor") + .with_stderr_data(str![[r#" +[ERROR] unexpected argument 'test_vendor' found + +Usage: cargo[EXE] vendor [OPTIONS] [path] + +For more information, try '--help'. + +"#]] + ) + .with_status(1) + .run(); + + p.cargo("vendor --respect-source-config --manifest-path foo/Cargo.toml -s bar/Cargo.toml -s baz/Cargo.toml test_vendor") + .run(); + + let lock = p.read_file("test_vendor/bitflags/Cargo.toml"); + assert!(lock.contains("version = \"0.8.0\"")); + let lock = p.read_file("test_vendor/bitflags-0.7.0/Cargo.toml"); + assert!(lock.contains("version = \"0.7.0\"")); +} + +#[cargo_test] +fn delete_old_crates() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bitflags = "=0.7.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("bitflags", "0.7.0").publish(); + Package::new("log", "0.3.5").publish(); + + p.cargo("vendor --respect-source-config").run(); + p.read_file("vendor/bitflags/Cargo.toml"); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + log = "=0.3.5" + "#, + ); + + p.cargo("vendor --respect-source-config").run(); + let lock = p.read_file("vendor/log/Cargo.toml"); + assert!(lock.contains("version = \"0.3.5\"")); + assert!(!p.root().join("vendor/bitflags/Cargo.toml").exists()); +} + +#[cargo_test] +fn ignore_files() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + url = "1.4.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("url", "1.4.1") + .file("src/lib.rs", "") + .file("foo.orig", "") + .file(".gitignore", "") + .file(".gitattributes", "") + .file("foo.rej", "") + .publish(); + + p.cargo("vendor --respect-source-config").run(); + let csum = p.read_file("vendor/url/.cargo-checksum.json"); + assert!(!csum.contains("foo.orig")); + assert!(!csum.contains(".gitignore")); + assert!(!csum.contains(".gitattributes")); + assert!(!csum.contains(".cargo-ok")); + assert!(!csum.contains("foo.rej")); +} + +#[cargo_test] +fn included_files_only() { + let git = git::new("a", |p| { + p.file("Cargo.toml", &basic_lib_manifest("a")) + .file("src/lib.rs", "") + .file(".gitignore", "a") + .file("a/b.md", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config").run(); + let csum = p.read_file("vendor/a/.cargo-checksum.json"); + assert!(!csum.contains("a/b.md")); +} + +#[cargo_test] +fn dependent_crates_in_crates() { + let git = git::new("a", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + + [dependencies] + b = { path = 'b' } + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_lib_manifest("b")) + .file("b/src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config").run(); + p.read_file("vendor/a/.cargo-checksum.json"); + p.read_file("vendor/b/.cargo-checksum.json"); +} + +#[cargo_test] +fn vendoring_git_crates() { + let git = git::new("git", |p| { + p.file("Cargo.toml", &basic_lib_manifest("serde_derive")) + .file("src/lib.rs", "") + .file("src/wut.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies.serde] + version = "0.5.0" + + [dependencies.serde_derive] + version = "0.5.0" + + [patch.crates-io] + serde_derive = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + Package::new("serde", "0.5.0") + .dep("serde_derive", "0.5") + .publish(); + Package::new("serde_derive", "0.5.0").publish(); + + p.cargo("vendor --respect-source-config").run(); + p.read_file("vendor/serde_derive/src/wut.rs"); + + add_crates_io_vendor_config(&p); + p.cargo("check").run(); +} + +#[cargo_test] +fn git_simple() { + let git = git::new("git", |p| { + p.file("Cargo.toml", &basic_lib_manifest("a")) + .file("src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config").run(); + let csum = p.read_file("vendor/a/.cargo-checksum.json"); + assert!(csum.contains("\"package\":null")); +} + +#[cargo_test] +fn git_diff_rev() { + let (git_project, git_repo) = git::new_repo("git", |p| { + p.file("Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("src/lib.rs", "") + }); + let url = git_project.url(); + let ref_1 = "v0.1.0"; + let ref_2 = "v0.2.0"; + + git::tag(&git_repo, ref_1); + + git_project.change_file("Cargo.toml", &basic_manifest("a", "0.2.0")); + git::add(&git_repo); + git::commit(&git_repo); + git::tag(&git_repo, ref_2); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a_1 = {{ package = "a", git = '{url}', rev = '{ref_1}' }} + a_2 = {{ package = "a", git = '{url}', rev = '{ref_2}' }} + "# + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config") + .with_stdout_data(str![[r#" +[source."git+[ROOTURL]/git?rev=v0.1.0"] +git = "[ROOTURL]/git" +rev = "v0.1.0" +replace-with = "vendored-sources" + +[source."git+[ROOTURL]/git?rev=v0.2.0"] +git = "[ROOTURL]/git" +rev = "v0.2.0" +replace-with = "vendored-sources" + +[source.vendored-sources] +directory = "vendor" + +"#]]) + .run(); +} + +#[cargo_test] +fn git_duplicate() { + let git = git::new("a", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "a" + version = "0.1.0" + + [dependencies] + b = { path = 'b' } + "#, + ) + .file("src/lib.rs", "") + .file("b/Cargo.toml", &basic_lib_manifest("b")) + .file("b/src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = {{ git = '{}' }} + b = '0.5.0' + + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + Package::new("b", "0.5.0").publish(); + + p.cargo("vendor --respect-source-config") + .with_stderr_data(str![[r#" +[UPDATING] git repository `[ROOTURL]/a` +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] b v0.5.0 (registry `dummy-registry`) +[ERROR] failed to sync + +Caused by: + found duplicate version of package `b v0.5.0` vendored from two sources: + + source 1: registry `crates-io` + source 2: [ROOTURL]/a#[..] + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn git_complex() { + let git_b = git::new("git_b", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "b" + version = "0.1.0" + edition = "2021" + + [dependencies] + dep_b = { path = 'dep_b' } + "#, + ) + .file("src/lib.rs", "") + .file("dep_b/Cargo.toml", &basic_lib_manifest("dep_b")) + .file("dep_b/src/lib.rs", "") + }); + + let git_a = git::new("git_a", |p| { + p.file( + "Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2021" + + [dependencies] + b = {{ git = '{}' }} + dep_a = {{ path = 'dep_a' }} + "#, + git_b.url() + ), + ) + .file("src/lib.rs", "") + .file("dep_a/Cargo.toml", &basic_lib_manifest("dep_a")) + .file("dep_a/src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + a = {{ git = '{}' }} + "#, + git_a.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + let output = p.cargo("vendor --respect-source-config").run(); + let output = String::from_utf8(output.stdout).unwrap(); + p.change_file(".cargo/config.toml", &output); + + p.cargo("check -v") + .with_stderr_data( + str![[r#" +[CHECKING] dep_b v0.5.0 ([ROOTURL]/git_b#[..]) +[CHECKING] dep_a v0.5.0 ([ROOTURL]/git_a#[..]) +[RUNNING] `rustc [..] [ROOT]/foo/vendor/dep_b/src/lib.rs [..]` +[RUNNING] `rustc [..] [ROOT]/foo/vendor/dep_a/src/lib.rs [..]` +[CHECKING] b v0.1.0 ([ROOTURL]/git_b#[..]) +[RUNNING] `rustc [..] [ROOT]/foo/vendor/b/src/lib.rs [..]` +[CHECKING] a v0.1.0 ([ROOTURL]/git_a#[..]) +[RUNNING] `rustc [..] [ROOT]/foo/vendor/a/src/lib.rs [..]` +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn git_deterministic() { + let git_dep = git::new("git_dep", |p| { + p.file( + "Cargo.toml", + r#" + [package] + name = "git_dep" + version = "0.0.1" + edition = "2021" + license = "MIT" + description = "foo" + documentation = "docs.rs/foo" + authors = [] + + [[example]] + name = "c" + + [[example]] + name = "b" + + [[example]] + name = "a" + "#, + ) + .file("src/lib.rs", "") + .file("examples/z.rs", "fn main() {}") + .file("examples/y.rs", "fn main() {}") + .file("examples/x.rs", "fn main() {}") + .file("examples/c.rs", "fn main() {}") + .file("examples/b.rs", "fn main() {}") + .file("examples/a.rs", "fn main() {}") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + git_dep = {{ git = '{}' }} + "#, + git_dep.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + let output = p.cargo("vendor --respect-source-config").run(); + let output = String::from_utf8(output.stdout).unwrap(); + p.change_file(".cargo/config.toml", &output); + + let git_dep_manifest = p.read_file("vendor/git_dep/Cargo.toml"); + assert_e2e().eq( + git_dep_manifest, + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "git_dep" +version = "0.0.1" +authors = [] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +documentation = "docs.rs/foo" +readme = false +license = "MIT" + +[lib] +name = "git_dep" +path = "src/lib.rs" + +[[example]] +name = "a" +path = "examples/a.rs" + +[[example]] +name = "b" +path = "examples/b.rs" + +[[example]] +name = "c" +path = "examples/c.rs" + +[[example]] +name = "x" +path = "examples/x.rs" + +[[example]] +name = "y" +path = "examples/y.rs" + +[[example]] +name = "z" +path = "examples/z.rs" + +"##]], + ); +} + +#[cargo_test] +fn git_update_rev() { + let (git_project, git_repo) = git::new_repo("git", |p| { + p.file("Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("src/lib.rs", "") + }); + let url = git_project.url(); + let ref_1 = "initial"; + let ref_2 = "update"; + + git::tag(&git_repo, ref_1); + + git_project.change_file("src/lib.rs", "pub fn f() {}"); + git::add(&git_repo); + git::commit(&git_repo); + git::tag(&git_repo, ref_2); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = {{ git = '{url}', rev = '{ref_1}' }} + "# + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config --versioned-dirs") + .run(); + + let lib = p.read_file("vendor/a-0.1.0/src/lib.rs"); + assert_e2e().eq(lib, ""); + + p.change_file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = {{ git = '{url}', rev = '{ref_2}' }} + "# + ), + ); + + p.cargo("vendor --respect-source-config --versioned-dirs") + .run(); + + let lib = p.read_file("vendor/a-0.1.0/src/lib.rs"); + assert_e2e().eq(lib, "pub fn f() {}"); +} + +#[cargo_test] +fn depend_on_vendor_dir_not_deleted() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + libc = "0.2.30" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("libc", "0.2.30").publish(); + + p.cargo("vendor --respect-source-config").run(); + assert!(p.root().join("vendor/libc").is_dir()); + + p.change_file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + libc = "0.2.30" + + [patch.crates-io] + libc = { path = 'vendor/libc' } + "#, + ); + + p.cargo("vendor --respect-source-config").run(); + assert!(p.root().join("vendor/libc").is_dir()); +} + +#[cargo_test] +fn ignore_hidden() { + // Don't delete files starting with `.` + Package::new("bar", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("vendor --respect-source-config").run(); + // Add a `.git` directory. + let repo = git::init(&p.root().join("vendor")); + git::add(&repo); + git::commit(&repo); + assert!(p.root().join("vendor/.git").exists()); + // Vendor again, shouldn't change anything. + p.cargo("vendor --respect-source-config").run(); + // .git should not be removed. + assert!(p.root().join("vendor/.git").exists()); + // And just for good measure, make sure no files changed. + let mut opts = git2::StatusOptions::new(); + assert!(repo + .statuses(Some(&mut opts)) + .unwrap() + .iter() + .all(|status| status.status() == git2::Status::CURRENT)); +} + +#[cargo_test] +fn config_instructions_works() { + // Check that the config instructions work for all dependency kinds. + registry::alt_init(); + Package::new("dep", "0.1.0").publish(); + Package::new("altdep", "0.1.0").alternative(true).publish(); + let git_project = git::new("gitdep", |project| { + project + .file("Cargo.toml", &basic_lib_manifest("gitdep")) + .file("src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + dep = "0.1" + altdep = {{version="0.1", registry="alternative"}} + gitdep = {{git='{}'}} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + let output = p.cargo("vendor --respect-source-config").run(); + let output = String::from_utf8(output.stdout).unwrap(); + p.change_file(".cargo/config.toml", &output); + + p.cargo("check -v") + .with_stderr_data( + str![[r#" +[CHECKING] altdep v0.1.0 (registry `alternative`) +[CHECKING] dep v0.1.0 +[RUNNING] `rustc [..] [ROOT]/foo/vendor/altdep/src/lib.rs [..]` +[RUNNING] `rustc [..] [ROOT]/foo/vendor/gitdep/src/lib.rs [..]` +[RUNNING] `rustc [..] [ROOT]/foo/vendor/dep/src/lib.rs [..]` +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[CHECKING] gitdep v0.5.0 ([ROOTURL]/gitdep#[..]) + +"#]] + .unordered(), + ) + .run(); +} + +#[cargo_test] +fn git_crlf_preservation() { + // Check that newlines don't get changed when you vendor + // (will only fail if your system is setup with core.autocrlf=true on windows) + let input = "hello \nthere\nmy newline\nfriends"; + let git_project = git::new("git", |p| { + p.file("Cargo.toml", &basic_lib_manifest("a")) + .file("src/lib.rs", input) + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + a = {{ git = '{}' }} + "#, + git_project.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + fs::write( + paths::home().join(".gitconfig"), + r#" + [core] + autocrlf = true + "#, + ) + .unwrap(); + + p.cargo("vendor --respect-source-config").run(); + let output = p.read_file("vendor/a/src/lib.rs"); + assert_eq!(input, output); +} + +#[cargo_test] +#[cfg(unix)] +fn vendor_preserves_permissions() { + use std::os::unix::fs::MetadataExt; + + Package::new("bar", "1.0.0") + .file_with_mode("example.sh", 0o755, "#!/bin/sh") + .file("src/lib.rs", "") + .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("vendor --respect-source-config").run(); + + let umask = cargo::util::get_umask(); + let metadata = fs::metadata(p.root().join("vendor/bar/src/lib.rs")).unwrap(); + assert_eq!(metadata.mode() & 0o777, 0o644 & !umask); + let metadata = fs::metadata(p.root().join("vendor/bar/example.sh")).unwrap(); + assert_eq!(metadata.mode() & 0o777, 0o755 & !umask); +} + +#[cargo_test] +fn no_remote_dependency_no_vendor() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [dependencies] + bar = { path = "bar" } + "#, + ) + .file("src/lib.rs", "") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + "#, + ) + .file("bar/src/lib.rs", "") + .build(); + + p.cargo("vendor") + .with_stderr_data(str![[r#" +[LOCKING] 1 package to latest compatible version +There is no dependency to vendor in this project. + +"#]]) + .run(); + assert!(!p.root().join("vendor").exists()); +} + +#[cargo_test] +fn vendor_crate_with_ws_inherit() { + let git = git::new("ws", |p| { + p.file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + [workspace.package] + version = "0.1.0" + "#, + ) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version.workspace = true + edition = "2021" + "#, + ) + .file("bar/src/lib.rs", "") + }); + + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2021" + + [dependencies] + bar = {{ git = '{}' }} + "#, + git.url() + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("vendor --respect-source-config").run(); + p.change_file( + ".cargo/config.toml", + &format!( + r#" + [source."{}"] + git = "{}" + replace-with = "vendor" + + [source.vendor] + directory = "vendor" + "#, + git.url(), + git.url() + ), + ); + + p.cargo("check -v") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOTURL]/ws#[..]) +[RUNNING] `rustc [..] [ROOT]/foo/vendor/bar/src/lib.rs [..]` +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[RUNNING] `rustc [..] src/lib.rs [..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/verify_project.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/verify_project.rs new file mode 100644 index 000000000..a02994da4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/verify_project.rs @@ -0,0 +1,85 @@ +//! Tests for the `cargo verify-project` command. + +use cargo_test_support::prelude::*; +use cargo_test_support::{basic_bin_manifest, main_file, project, str}; + +#[cargo_test] +fn cargo_verify_project_path_to_cargo_toml_relative() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("verify-project --manifest-path foo/Cargo.toml") + .cwd(p.root().parent().unwrap()) + .with_stdout_data(str![[r#" +{"success":"true"} + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_verify_project_path_to_cargo_toml_absolute() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("verify-project --manifest-path") + .arg(p.root().join("Cargo.toml")) + .cwd(p.root().parent().unwrap()) + .with_stdout_data(str![[r#" +{"success":"true"} + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_verify_project_cwd() { + let p = project() + .file("Cargo.toml", &basic_bin_manifest("foo")) + .file("src/foo.rs", &main_file(r#""i am foo""#, &[])) + .build(); + + p.cargo("verify-project") + .with_stdout_data(str![[r#" +{"success":"true"} + +"#]]) + .run(); +} + +#[cargo_test] +fn cargo_verify_project_honours_unstable_features() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["test-dummy-unstable"] + + [package] + name = "foo" + version = "0.0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("verify-project") + .masquerade_as_nightly_cargo(&["test-dummy-unstable"]) + .with_stdout_data(str![[r#" +{"success":"true"} + +"#]]) + .run(); + + p.cargo("verify-project") + .with_status(1) + .with_stdout_data(str![[r#" +{"invalid":"failed to parse manifest at `[..]`"} + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/version.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/version.rs new file mode 100644 index 000000000..83f2d2b78 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/version.rs @@ -0,0 +1,70 @@ +//! Tests for displaying the cargo version. + +use cargo_test_support::prelude::*; +use cargo_test_support::{cargo_process, project}; + +#[cargo_test] +fn simple() { + let p = project().build(); + + p.cargo("version") + .with_stdout_data(&format!("cargo {}\n", cargo::version())) + .run(); + + p.cargo("--version") + .with_stdout_data(&format!("cargo {}\n", cargo::version())) + .run(); + + p.cargo("-V") + .with_stdout_data(&format!("cargo {}\n", cargo::version())) + .run(); +} + +#[cargo_test] +fn version_works_without_rustc() { + let p = project().build(); + p.cargo("version").env("PATH", "").run(); +} + +#[cargo_test] +fn version_works_with_bad_config() { + let p = project() + .file(".cargo/config.toml", "this is not toml") + .build(); + p.cargo("version").run(); +} + +#[cargo_test] +fn version_works_with_bad_target_dir() { + let p = project() + .file( + ".cargo/config.toml", + r#" + [build] + target-dir = 4 + "#, + ) + .build(); + p.cargo("version").run(); +} + +#[cargo_test] +fn verbose() { + // This is mainly to check that it doesn't explode. + cargo_process("-vV") + .with_stdout_data(format!( + "\ +cargo {} +release: [..] +commit-hash: [..] +commit-date: [..] +host: [HOST_TARGET] +libgit2: [..] (sys:[..] [..]) +libcurl: [..] (sys:[..] [..]) +... +os: [..] +", + cargo::version() + )) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warn_on_failure.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warn_on_failure.rs new file mode 100644 index 000000000..f5b91597e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warn_on_failure.rs @@ -0,0 +1,125 @@ +//! Tests for whether or not warnings are displayed for build scripts. + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::{project, str, Project}; + +static WARNING1: &str = "Hello! I'm a warning. :)"; +static WARNING2: &str = "And one more!"; + +fn make_lib(lib_src: &str) { + Package::new("bar", "0.0.1") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + authors = [] + version = "0.0.1" + edition = "2015" + build = "build.rs" + "#, + ) + .file( + "build.rs", + &format!( + r#" + fn main() {{ + use std::io::Write; + println!("cargo::warning={{}}", "{}"); + println!("hidden stdout"); + write!(&mut ::std::io::stderr(), "hidden stderr"); + println!("cargo::warning={{}}", "{}"); + }} + "#, + WARNING1, WARNING2 + ), + ) + .file("src/lib.rs", &format!("fn f() {{ {} }}", lib_src)) + .publish(); +} + +fn make_upstream(main_src: &str) -> Project { + project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("src/main.rs", &format!("fn main() {{ {} }}", main_src)) + .build() +} + +#[cargo_test] +fn no_warning_on_success() { + make_lib(""); + let upstream = make_upstream(""); + upstream + .cargo("build") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn no_warning_on_bin_failure() { + make_lib(""); + let upstream = make_upstream("hi()"); + upstream + .cargo("build") + .with_status(101) + .with_stdout_does_not_contain("hidden stdout") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +[COMPILING] foo v0.0.1 ([ROOT]/foo) +error[E0425]: cannot find function `hi` in this scope +... +[ERROR] could not compile `foo` (bin "foo") due to 1 previous error + +"#]]) + .run(); +} + +#[cargo_test] +fn warning_on_lib_failure() { + make_lib("err()"); + let upstream = make_upstream(""); + upstream + .cargo("build") + .with_status(101) + .with_stdout_does_not_contain("hidden stdout") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`) +[COMPILING] bar v0.0.1 +error[E0425]: cannot find function `err` in this scope +... +[WARNING] bar@0.0.1: Hello! I'm a warning. :) +[WARNING] bar@0.0.1: And one more! +[ERROR] could not compile `bar` (lib) due to 1 previous error + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warning_override.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warning_override.rs new file mode 100644 index 000000000..f78f7368f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/warning_override.rs @@ -0,0 +1,221 @@ +//! Tests for overriding warning behavior using `build.warnings` config option. + +use cargo_test_support::{cargo_test, project, str, tools, Project}; + +fn make_project_with_rustc_warning() -> Project { + project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2021" + "# + ), + ) + .file("src/main.rs", "fn main() { let x = 3; }") + .build() +} + +#[cargo_test] +fn rustc_caching_allow_first() { + let p = make_project_with_rustc_warning(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .arg("--config") + .arg("build.warnings='allow'") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .arg("--config") + .arg("build.warnings='deny'") + .with_stderr_data(str![[r#" +[WARNING] unused variable: `x` + --> src/main.rs:1:17 + | +1 | fn main() { let x = 3; } + | ^ [HELP] if this is intentional, prefix it with an underscore: `_x` + | + = [NOTE] `#[warn(unused_variables)]` on by default + +[WARNING] `foo` (bin "foo") generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[ERROR] warnings are denied by `build.warnings` configuration + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn rustc_caching_deny_first() { + let p = make_project_with_rustc_warning(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .arg("--config") + .arg("build.warnings='deny'") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] unused variable: `x` + --> src/main.rs:1:17 + | +1 | fn main() { let x = 3; } + | ^ [HELP] if this is intentional, prefix it with an underscore: `_x` + | + = [NOTE] `#[warn(unused_variables)]` on by default + +[WARNING] `foo` (bin "foo") generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[ERROR] warnings are denied by `build.warnings` configuration + +"#]]) + .with_status(101) + .run(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .arg("--config") + .arg("build.warnings='allow'") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn config() { + let p = make_project_with_rustc_warning(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .env("CARGO_BUILD_WARNINGS", "deny") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] unused variable: `x` + --> src/main.rs:1:17 + | +1 | fn main() { let x = 3; } + | ^ [HELP] if this is intentional, prefix it with an underscore: `_x` + | + = [NOTE] `#[warn(unused_variables)]` on by default + +[WARNING] `foo` (bin "foo") generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[ERROR] warnings are denied by `build.warnings` configuration + +"#]]) + .with_status(101) + .run(); + + // CLI has precedence over env + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .arg("--config") + .arg("build.warnings='warn'") + .env("CARGO_BUILD_WARNINGS", "deny") + .with_stderr_data(str![[r#" +[WARNING] unused variable: `x` + --> src/main.rs:1:17 + | +1 | fn main() { let x = 3; } + | ^ [HELP] if this is intentional, prefix it with an underscore: `_x` + | + = [NOTE] `#[warn(unused_variables)]` on by default + +[WARNING] `foo` (bin "foo") generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn requires_nightly() { + // build.warnings has no effect without -Zwarnings. + let p = make_project_with_rustc_warning(); + p.cargo("check") + .arg("--config") + .arg("build.warnings='deny'") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] unused variable: `x` + --> src/main.rs:1:17 + | +1 | fn main() { let x = 3; } + | ^ [HELP] if this is intentional, prefix it with an underscore: `_x` + | + = [NOTE] `#[warn(unused_variables)]` on by default + +[WARNING] `foo` (bin "foo") generated 1 warning +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn clippy() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/lib.rs", "use std::io;") // <-- unused import + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .arg("--config") + .arg("build.warnings='deny'") + .env("RUSTC_WORKSPACE_WRAPPER", tools::wrapped_clippy_driver()) + .with_stderr_data(str![[r#" +[CHECKING] foo v0.0.1 ([ROOT]/foo) +[WARNING] unused import: `std::io` +... +[WARNING] `foo` (lib) generated 1 warning (run `cargo clippy --fix --lib -p foo` to apply 1 suggestion) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[ERROR] warnings are denied by `build.warnings` configuration + +"#]]) + .with_status(101) + .run(); +} + +#[cargo_test] +fn unknown_value() { + let p = make_project_with_rustc_warning(); + p.cargo("check") + .masquerade_as_nightly_cargo(&["warnings"]) + .arg("-Zwarnings") + .arg("--config") + .arg("build.warnings='forbid'") + .with_stderr_data(str![[r#" +[ERROR] error in --config cli option: could not load config key `build.warnings` + +Caused by: + unknown variant `forbid`, expected one of `warn`, `allow`, `deny` + +"#]]) + .with_status(101) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/weak_dep_features.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/weak_dep_features.rs new file mode 100644 index 000000000..583f67c8b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/weak_dep_features.rs @@ -0,0 +1,668 @@ +//! Tests for weak-dep-features. + +use std::fmt::Write; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::{Dependency, Package, RegistryBuilder}; +use cargo_test_support::str; +use cargo_test_support::{project, publish}; + +use super::features2::switch_to_resolver_2; + +// Helper to create lib.rs files that check features. +fn require(enabled_features: &[&str], disabled_features: &[&str]) -> String { + let mut s = String::new(); + writeln!(s, "#![allow(unexpected_cfgs)]").unwrap(); + for feature in enabled_features { + writeln!(s, "#[cfg(not(feature=\"{feature}\"))] compile_error!(\"expected feature {feature} to be enabled\");", + feature=feature).unwrap(); + } + for feature in disabled_features { + writeln!(s, "#[cfg(feature=\"{feature}\")] compile_error!(\"did not expect feature {feature} to be enabled\");", + feature=feature).unwrap(); + } + s +} + +#[cargo_test] +fn simple() { + Package::new("bar", "1.0.0") + .feature("feat", &[]) + .file("src/lib.rs", &require(&["feat"], &[])) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional = true } + + [features] + f1 = ["bar?/feat"] + "#, + ) + .file("src/lib.rs", &require(&["f1"], &[])) + .build(); + + // It's a bit unfortunate that this has to download `bar`, but avoiding + // that is extremely difficult. + p.cargo("check --features f1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check --features f1,bar") + .with_stderr_data(str![[r#" +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn deferred() { + // A complex chain that requires deferring enabling the feature due to + // another dependency getting enabled. + Package::new("bar", "1.0.0") + .feature("feat", &[]) + .file("src/lib.rs", &require(&["feat"], &[])) + .publish(); + Package::new("dep", "1.0.0") + .add_dep(Dependency::new("bar", "1.0").optional(true)) + .feature("feat", &["bar?/feat"]) + .publish(); + Package::new("bar_activator", "1.0.0") + .feature_dep("dep", "1.0", &["bar"]) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = { version = "1.0", features = ["feat"] } + bar_activator = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] dep v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar_activator v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] bar v1.0.0 +[CHECKING] dep v1.0.0 +[CHECKING] bar_activator v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn not_optional_dep() { + // Attempt to use dep_name?/feat where dep_name is not optional. + Package::new("dep", "1.0.0").feature("feat", &[]).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + dep = "1.0" + + [features] + feat = ["dep?/feat"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to parse manifest at `[ROOT]/foo/Cargo.toml` + +Caused by: + feature `feat` includes `dep?/feat` with a `?`, but `dep` is not an optional dependency + A non-optional dependency of the same name is defined; consider removing the `?` or changing the dependency to be optional + +"#]]) + .run(); +} + +#[cargo_test] +fn optional_cli_syntax() { + // --features bar?/feat + Package::new("bar", "1.0.0") + .feature("feat", &[]) + .file("src/lib.rs", &require(&["feat"], &[])) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional = true } + "#, + ) + .file("src/lib.rs", "") + .build(); + + // Does not build bar. + p.cargo("check --features bar?/feat") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Builds bar. + p.cargo("check --features bar?/feat,bar") + .with_stderr_data(str![[r#" +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + eprintln!("check V2 resolver"); + switch_to_resolver_2(&p); + p.build_dir().rm_rf(); + // Does not build bar. + p.cargo("check --features bar?/feat") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Builds bar. + p.cargo("check --features bar?/feat,bar") + .with_stderr_data(str![[r#" +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn required_features() { + // required-features doesn't allow ? + Package::new("bar", "1.0.0").feature("feat", &[]).publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional = true } + + [[bin]] + name = "foo" + required-features = ["bar?/feat"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ERROR] invalid feature `bar?/feat` in required-features of target `foo`: optional dependency with `?` is not allowed in required-features + +"#]]) + .run(); +} + +#[cargo_test] +fn weak_with_host_decouple() { + // weak-dep-features with new resolver + // + // foo v0.1.0 + // └── common v1.0.0 + // └── bar v1.0.0 <-- does not have `feat` enabled + // [build-dependencies] + // └── bar_activator v1.0.0 + // └── common v1.0.0 + // └── bar v1.0.0 <-- does have `feat` enabled + Package::new("bar", "1.0.0") + .feature("feat", &[]) + .file( + "src/lib.rs", + r#" + pub fn feat() -> bool { + cfg!(feature = "feat") + } + "#, + ) + .publish(); + + Package::new("common", "1.0.0") + .add_dep(Dependency::new("bar", "1.0").optional(true)) + .feature("feat", &["bar?/feat"]) + .file( + "src/lib.rs", + r#" + #[cfg(feature = "bar")] + pub fn feat() -> bool { bar::feat() } + #[cfg(not(feature = "bar"))] + pub fn feat() -> bool { false } + "#, + ) + .publish(); + + Package::new("bar_activator", "1.0.0") + .feature_dep("common", "1.0", &["bar", "feat"]) + .file( + "src/lib.rs", + r#" + pub fn feat() -> bool { + common::feat() + } + "#, + ) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + resolver = "2" + + [dependencies] + common = { version = "1.0", features = ["feat"] } + + [build-dependencies] + bar_activator = "1.0" + "#, + ) + .file( + "src/main.rs", + r#" + fn main() { + assert!(!common::feat()); + } + "#, + ) + .file( + "build.rs", + r#" + fn main() { + assert!(bar_activator::feat()); + } + "#, + ) + .build(); + + p.cargo("run") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 3 packages to latest compatible versions +[DOWNLOADING] crates ... +[DOWNLOADED] common v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar_activator v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[COMPILING] bar v1.0.0 +[COMPILING] common v1.0.0 +[COMPILING] bar_activator v1.0.0 +[COMPILING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[RUNNING] `target/debug/foo[EXE]` + +"#]]) + .run(); +} + +#[cargo_test] +fn weak_namespaced() { + // Behavior with a dep: dependency. + Package::new("bar", "1.0.0") + .feature("feat", &[]) + .file("src/lib.rs", &require(&["feat"], &[])) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional = true } + + [features] + f1 = ["bar?/feat"] + f2 = ["dep:bar"] + "#, + ) + .file("src/lib.rs", &require(&["f1"], &["f2", "bar"])) + .build(); + + p.cargo("check --features f1") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] bar v1.0.0 (registry `dummy-registry`) +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("tree -f") + .arg("{p} feats:{f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) feats: + +"#]]) + .run(); + + p.cargo("tree --features f1 -f") + .arg("{p} feats:{f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) feats:f1 + +"#]]) + .run(); + + p.cargo("tree --features f1,f2 -f") + .arg("{p} feats:{f}") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) feats:f1,f2 +└── bar v1.0.0 feats:feat + +"#]]) + .run(); + + // "bar" remains not-a-feature + p.change_file("src/lib.rs", &require(&["f1", "f2"], &["bar"])); + + p.cargo("check --features f1,f2") + .with_stderr_data(str![[r#" +[CHECKING] bar v1.0.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn tree() { + Package::new("bar", "1.0.0") + .feature("feat", &[]) + .file("src/lib.rs", &require(&["feat"], &[])) + .publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + bar = { version = "1.0", optional = true } + + [features] + f1 = ["bar?/feat"] + "#, + ) + .file("src/lib.rs", &require(&["f1"], &[])) + .build(); + + p.cargo("tree --features f1") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + p.cargo("tree --features f1,bar") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --features f1,bar -e features") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) +└── bar feature "default" + └── bar v1.0.0 + +"#]]) + .run(); + + p.cargo("tree --features f1,bar -e features -i bar") + .with_stdout_data(str![[r#" +bar v1.0.0 +├── bar feature "default" +│ └── foo v0.1.0 ([ROOT]/foo) +│ ├── foo feature "bar" (command-line) +│ ├── foo feature "default" (command-line) +│ └── foo feature "f1" (command-line) +└── bar feature "feat" + └── foo feature "f1" (command-line) + +"#]]) + .run(); + + p.cargo("tree -e features --features bar?/feat") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); + + // This is a little strange in that it produces no output. + // Maybe `cargo tree` should print a note about why? + p.cargo("tree -e features -i bar --features bar?/feat") + .with_stdout_data("") + .run(); + + p.cargo("tree -e features -i bar --features bar?/feat,bar") + .with_stdout_data(str![[r#" +bar v1.0.0 +├── bar feature "default" +│ └── foo v0.1.0 ([ROOT]/foo) +│ ├── foo feature "bar" (command-line) +│ └── foo feature "default" (command-line) +└── bar feature "feat" (command-line) + +"#]]) + .run(); +} + +#[cargo_test] +fn publish() { + let registry = RegistryBuilder::new().http_api().http_index().build(); + + // Publish behavior with /? syntax. + Package::new("bar", "1.0.0").feature("feat", &[]).publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + description = "foo" + license = "MIT" + homepage = "https://example.com/" + + [dependencies] + bar = { version = "1.0", optional = true } + + [features] + feat1 = [] + feat2 = ["bar?/feat"] + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("publish") + .replace_crates_io(registry.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[PACKAGING] foo v0.1.0 ([ROOT]/foo) +[UPDATING] crates.io index +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.1.0 ([ROOT]/foo) +[COMPILING] foo v0.1.0 ([ROOT]/foo/target/package/foo-0.1.0) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.1.0 ([ROOT]/foo) +[UPLOADED] foo v0.1.0 to registry `crates-io` +[NOTE] waiting for `foo v0.1.0` to be available at registry `crates-io`. +You may press ctrl-c to skip waiting; the crate should be available shortly. +[PUBLISHED] foo v0.1.0 at registry `crates-io` + +"#]]) + .run(); + + publish::validate_upload_with_contents( + r#" + { + "authors": [], + "badges": {}, + "categories": [], + "deps": [ + { + "default_features": true, + "features": [], + "kind": "normal", + "name": "bar", + "optional": true, + "target": null, + "version_req": "^1.0" + } + ], + "description": "foo", + "documentation": null, + "features": { + "feat1": [], + "feat2": ["bar?/feat"] + }, + "homepage": "https://example.com/", + "keywords": [], + "license": "MIT", + "license_file": null, + "links": null, + "name": "foo", + "readme": null, + "readme_file": null, + "repository": null, + "rust_version": null, + "vers": "0.1.0" + } + "#, + "foo-0.1.0.crate", + &["Cargo.toml", "Cargo.toml.orig", "src/lib.rs", "Cargo.lock"], + [( + "Cargo.toml", + str![[r##" +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2015" +name = "foo" +version = "0.1.0" +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "foo" +homepage = "https://example.com/" +readme = false +license = "MIT" + +[features] +feat1 = [] +feat2 = ["bar?/feat"] + +[lib] +name = "foo" +path = "src/lib.rs" + +[dependencies.bar] +version = "1.0" +optional = true + +"##]], + )], + ); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/workspaces.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/workspaces.rs new file mode 100644 index 000000000..692212c52 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/workspaces.rs @@ -0,0 +1,2718 @@ +//! Tests for workspaces. + +use std::env; +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::registry::Package; +use cargo_test_support::str; +use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project, sleep_ms}; + +#[cargo_test] +fn simple_explicit() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + assert!(!p.bin("bar").is_file()); + + p.cargo("build").cwd("bar").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + + assert!(p.root().join("Cargo.lock").is_file()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); +} + +#[cargo_test] +fn simple_explicit_default_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + default-members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("build").run(); + assert!(p.bin("bar").is_file()); + assert!(!p.bin("foo").is_file()); +} + +#[cargo_test] +fn non_virtual_default_members_build_other_member() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = [".", "bar", "baz"] + default-members = ["baz"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] baz v0.1.0 ([ROOT]/foo/baz) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check --manifest-path bar/Cargo.toml") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn non_virtual_default_members_build_root_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + default-members = ["."] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .build(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn inferred_root() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + assert!(!p.bin("bar").is_file()); + + p.cargo("build").cwd("bar").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + + assert!(p.root().join("Cargo.lock").is_file()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); +} + +#[cargo_test] +fn inferred_path_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", ""); + let p = p.build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + assert!(!p.bin("bar").is_file()); + + p.cargo("build").cwd("bar").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + + assert!(p.root().join("Cargo.lock").is_file()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); +} + +#[cargo_test] +fn transitive_path_dep() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "bar" } + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + baz = { path = "../baz" } + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", "") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/main.rs", "fn main() {}") + .file("baz/src/lib.rs", ""); + let p = p.build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + assert!(!p.bin("bar").is_file()); + assert!(!p.bin("baz").is_file()); + + p.cargo("build").cwd("bar").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + assert!(!p.bin("baz").is_file()); + + p.cargo("build").cwd("baz").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + assert!(p.bin("baz").is_file()); + + assert!(p.root().join("Cargo.lock").is_file()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); + assert!(!p.root().join("baz/Cargo.lock").is_file()); +} + +#[cargo_test] +fn parent_pointer_works() { + let p = project() + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "../bar" } + + [workspace] + "#, + ) + .file("foo/src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../foo" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file("bar/src/lib.rs", ""); + let p = p.build(); + + p.cargo("build").cwd("foo").run(); + p.cargo("build").cwd("bar").run(); + assert!(p.root().join("foo/Cargo.lock").is_file()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); +} + +#[cargo_test] +fn same_names_in_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] two packages named `foo` in this workspace: +- [ROOT]/foo/bar/Cargo.toml +- [ROOT]/foo/Cargo.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn parent_doesnt_point_to_child() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .cwd("bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] current package believes it's in a workspace when it's not: +current: [ROOT]/foo/bar/Cargo.toml +workspace: [ROOT]/foo/Cargo.toml + +this may be fixable by ensuring that this crate is depended on by the workspace root: [ROOT]/foo/Cargo.toml +Alternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest. + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_parent_pointer() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to read `[ROOT]/foo/foo/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn invalid_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["foo"] + "#, + ) + .file("src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to load manifest for workspace member `[ROOT]/foo/foo` +referenced by workspace at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to read `[ROOT]/foo/foo/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn bare_workspace_ok() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + "#, + ) + .file("src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn two_roots() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = [".."] + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] multiple workspace roots found in the same workspace: + [ROOT]/foo/bar + [ROOT]/foo + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_isnt_root() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] root of a workspace inferred but wasn't a root: [ROOT]/foo/bar/Cargo.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn dangling_member() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../baz" + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../baz" + "#, + ) + .file("baz/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package `[ROOT]/foo/bar/Cargo.toml` is a member of the wrong workspace +expected: [ROOT]/foo/Cargo.toml +actual: [ROOT]/foo/baz/Cargo.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn cycle() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "bar" + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] root of a workspace inferred but wasn't a root: [ROOT]/foo/bar/Cargo.toml + +"#]]) + .run(); +} + +#[cargo_test] +fn share_dependencies() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = "0.1" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = "< 0.1.5" + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + Package::new("dep1", "0.1.3").publish(); + Package::new("dep1", "0.1.8").publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[ADDING] dep1 v0.1.3 (available: v0.1.8) +[DOWNLOADING] crates ... +[DOWNLOADED] dep1 v0.1.3 (registry `dummy-registry`) +[CHECKING] dep1 v0.1.3 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn fetch_fetches_all() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = "*" + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + Package::new("dep1", "0.1.3").publish(); + + p.cargo("fetch") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to latest compatible version +[DOWNLOADING] crates ... +[DOWNLOADED] dep1 v0.1.3 (registry `dummy-registry`) + +"#]]) + .run(); +} + +#[cargo_test] +fn lock_works_for_everyone() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep2 = "0.1" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + dep1 = "0.1" + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + Package::new("dep1", "0.1.0").publish(); + Package::new("dep2", "0.1.0").publish(); + + p.cargo("generate-lockfile") + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 2 packages to latest compatible versions + +"#]]) + .run(); + + Package::new("dep1", "0.1.1").publish(); + Package::new("dep2", "0.1.1").publish(); + + p.cargo("check") + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] dep2 v0.1.0 (registry `dummy-registry`) +[CHECKING] dep2 v0.1.0 +[CHECKING] foo v0.1.0 ([ROOT]/foo) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + p.cargo("check") + .cwd("bar") + .with_stderr_data(str![[r#" +[DOWNLOADING] crates ... +[DOWNLOADED] dep1 v0.1.0 (registry `dummy-registry`) +[CHECKING] dep1 v0.1.0 +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_works() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + p.cargo("build").cwd("bar").run(); + assert!(p.root().join("Cargo.lock").is_file()); + assert!(p.bin("bar").is_file()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); +} + +#[cargo_test] +fn explicit_package_argument_works_with_virtual_manifest() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + p.cargo("build --package bar").run(); + assert!(p.root().join("Cargo.lock").is_file()); + assert!(p.bin("bar").is_file()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); +} + +#[cargo_test] +fn virtual_misconfigure() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + p.cargo("check") + .cwd("bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] current package believes it's in a workspace when it's not: +current: [ROOT]/foo/bar/Cargo.toml +workspace: [ROOT]/foo/Cargo.toml + +this may be fixable by adding `bar` to the `workspace.members` array of the manifest located at: [ROOT]/foo/Cargo.toml +Alternatively, to keep it out of the workspace, add the package to the `workspace.exclude` array, or add an empty `[workspace]` table to the package's manifest. + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_build_all_implied() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + p.cargo("check").run(); +} + +#[cargo_test] +fn virtual_default_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + default-members = ["bar"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}") + .file("baz/src/main.rs", "fn main() {}"); + let p = p.build(); + p.cargo("build").run(); + assert!(p.bin("bar").is_file()); + assert!(!p.bin("baz").is_file()); +} + +#[cargo_test] +fn virtual_default_member_is_not_a_member() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar"] + default-members = ["something-else"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package `[ROOT]/foo/something-else` is listed in default-members but is not a member +for workspace at `[ROOT]/foo/Cargo.toml`. + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_default_members_build_other_member() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["bar", "baz"] + default-members = ["baz"] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", "pub fn bar() {}") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", "pub fn baz() {}") + .build(); + + p.cargo("check --manifest-path bar/Cargo.toml") + .with_stderr_data(str![[r#" +[CHECKING] bar v0.1.0 ([ROOT]/foo/bar) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn virtual_build_no_members() { + let p = project().file( + "Cargo.toml", + r#" + [workspace] + "#, + ); + let p = p.build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] manifest path `[ROOT]/foo` contains no package: The manifest is virtual, and the workspace has no members. + +"#]]) + .run(); +} + +#[cargo_test] +fn include_virtual() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "") + .file( + "bar/Cargo.toml", + r#" + [workspace] + "#, + ); + let p = p.build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] multiple workspace roots found in the same workspace: + [ROOT]/foo/bar + [ROOT]/foo + +"#]]) + .run(); +} + +#[cargo_test] +fn members_include_path_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["p1"] + + [dependencies] + p3 = { path = "p3" } + "#, + ) + .file("src/lib.rs", "") + .file( + "p1/Cargo.toml", + r#" + [package] + name = "p1" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + p2 = { path = "../p2" } + "#, + ) + .file("p1/src/lib.rs", "") + .file("p2/Cargo.toml", &basic_manifest("p2", "0.1.0")) + .file("p2/src/lib.rs", "") + .file("p3/Cargo.toml", &basic_manifest("p3", "0.1.0")) + .file("p3/src/lib.rs", ""); + let p = p.build(); + + p.cargo("check").cwd("p1").run(); + p.cargo("check").cwd("p2").run(); + p.cargo("check").cwd("p3").run(); + p.cargo("check").run(); + + assert!(p.root().join("target").is_dir()); + assert!(!p.root().join("p1/target").is_dir()); + assert!(!p.root().join("p2/target").is_dir()); + assert!(!p.root().join("p3/target").is_dir()); +} + +#[cargo_test] +fn new_creates_members_list() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + "#, + ) + .file("src/lib.rs", ""); + let p = p.build(); + + p.cargo("new --lib bar").with_stderr_data(str![[r#" +[CREATING] library `bar` package +[ADDING] `bar` as member of workspace at `[ROOT]/foo` +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]).run(); +} + +#[cargo_test] +fn new_warning_with_corrupt_ws() { + let p = project().file("Cargo.toml", "asdf").build(); + p.cargo("new bar").with_stderr_data(str![[r#" +[CREATING] binary (application) `bar` package +[ERROR] expected `.`, `=` + --> Cargo.toml:1:5 + | +1 | asdf + | ^ + | +[WARNING] compiling this new package may not work due to invalid workspace configuration + +[NOTE] see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +"#]]).run(); +} + +#[cargo_test] +fn lock_doesnt_change_depending_on_crate() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ['baz'] + + [dependencies] + foo = "*" + "#, + ) + .file("src/lib.rs", "") + .file( + "baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = "*" + "#, + ) + .file("baz/src/lib.rs", ""); + let p = p.build(); + + Package::new("foo", "1.0.0").publish(); + Package::new("bar", "1.0.0").publish(); + + p.cargo("check").run(); + + let lockfile = p.read_lockfile(); + + p.cargo("check").cwd("baz").run(); + + let lockfile2 = p.read_lockfile(); + + assert_eq!(lockfile, lockfile2); +} + +#[cargo_test] +fn rebuild_please() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ['lib', 'bin'] + "#, + ) + .file("lib/Cargo.toml", &basic_manifest("lib", "0.1.0")) + .file( + "lib/src/lib.rs", + r#" + pub fn foo() -> u32 { 0 } + "#, + ) + .file( + "bin/Cargo.toml", + r#" + [package] + name = "bin" + version = "0.1.0" + edition = "2015" + + [dependencies] + lib = { path = "../lib" } + "#, + ) + .file( + "bin/src/main.rs", + r#" + extern crate lib; + + fn main() { + assert_eq!(lib::foo(), 0); + } + "#, + ); + let p = p.build(); + + p.cargo("run").cwd("bin").run(); + + sleep_ms(1000); + + p.change_file("lib/src/lib.rs", "pub fn foo() -> u32 { 1 }"); + + p.cargo("build").cwd("lib").run(); + + p.cargo("run") + .cwd("bin") + .with_status(101) + .with_stderr_data(str![[r#" +... +assertion[..] +... +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_in_git() { + let git_project = git::new("dep1", |project| { + project + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "lib" + version = "0.1.0" + edition = "2015" + + [dependencies.foo] + git = '{}' + "#, + git_project.url() + ), + ) + .file( + "src/lib.rs", + r#" + pub fn foo() -> u32 { 0 } + "#, + ); + let p = p.build(); + + p.cargo("check").run(); +} + +#[cargo_test] +fn lockfile_can_specify_nonexistent_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/main.rs", "fn main() {}") + .file( + "Cargo.lock", + r#" + [[package]] + name = "a" + version = "0.1.0" + + [[package]] + name = "b" + version = "0.1.0" + "#, + ); + + let p = p.build(); + + p.cargo("check").cwd("a").run(); +} + +#[cargo_test] +fn you_cannot_generate_lockfile_for_empty_workspaces() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + "#, + ) + .file("bar/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("update") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] you can't generate a lockfile for an empty workspace. + +"#]]) + .run(); +} + +#[cargo_test] +fn workspace_with_transitive_dev_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.5.0" + edition = "2015" + authors = ["mbrubeck@example.com"] + + [dependencies.bar] + path = "bar" + + [workspace] + "#, + ) + .file("src/main.rs", r#"fn main() {}"#) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.5.0" + edition = "2015" + authors = ["mbrubeck@example.com"] + + [dev-dependencies.baz] + path = "../baz" + "#, + ) + .file( + "bar/src/lib.rs", + r#" + pub fn init() {} + + #[cfg(test)] + + #[test] + fn test() { + extern crate baz; + baz::do_stuff(); + } + "#, + ) + .file("baz/Cargo.toml", &basic_manifest("baz", "0.5.0")) + .file("baz/src/lib.rs", r#"pub fn do_stuff() {}"#); + let p = p.build(); + + p.cargo("test -p bar").run(); +} + +#[cargo_test] +fn error_if_parent_cargo_toml_is_invalid() { + let p = project() + .file("Cargo.toml", "Totally not a TOML file") + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .cwd("bar") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] expected `.`, `=` + --> ../Cargo.toml:1:9 + | +1 | Totally not a TOML file + | ^ + | + +"#]]) + .run(); +} + +#[cargo_test] +fn relative_path_for_member_works() { + let p = project() + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["../bar"] + "#, + ) + .file("foo/src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../foo" + "#, + ) + .file("bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check").cwd("foo").run(); + p.cargo("check").cwd("bar").run(); +} + +#[cargo_test] +fn relative_path_for_root_works() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + + [dependencies] + subproj = { path = "./subproj" } + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("subproj/Cargo.toml", &basic_manifest("subproj", "0.1.0")) + .file("subproj/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check --manifest-path ./Cargo.toml").run(); + + p.cargo("check --manifest-path ../Cargo.toml") + .cwd("subproj") + .run(); +} + +#[cargo_test] +fn path_dep_outside_workspace_is_not_member() { + let p = project() + .no_manifest() + .file( + "ws/Cargo.toml", + r#" + [package] + name = "ws" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = "../foo" } + + [workspace] + "#, + ) + .file("ws/src/lib.rs", "extern crate foo;") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", ""); + let p = p.build(); + + p.cargo("check").cwd("ws").run(); +} + +#[cargo_test] +fn test_in_and_out_of_workspace() { + let p = project() + .no_manifest() + .file( + "ws/Cargo.toml", + r#" + [package] + name = "ws" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = "../foo" } + + [workspace] + members = [ "../bar" ] + "#, + ) + .file("ws/src/lib.rs", "extern crate foo; pub fn f() { foo::f() }") + .file( + "foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "../bar" } + "#, + ) + .file( + "foo/src/lib.rs", + "extern crate bar; pub fn f() { bar::f() }", + ) + .file( + "bar/Cargo.toml", + r#" + [package] + workspace = "../ws" + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file("bar/src/lib.rs", "pub fn f() { }"); + let p = p.build(); + + p.cargo("check").cwd("ws").run(); + + assert!(p.root().join("ws/Cargo.lock").is_file()); + assert!(p.root().join("ws/target").is_dir()); + assert!(!p.root().join("foo/Cargo.lock").is_file()); + assert!(!p.root().join("foo/target").is_dir()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); + assert!(!p.root().join("bar/target").is_dir()); + + p.cargo("check").cwd("foo").run(); + assert!(p.root().join("foo/Cargo.lock").is_file()); + assert!(p.root().join("foo/target").is_dir()); + assert!(!p.root().join("bar/Cargo.lock").is_file()); + assert!(!p.root().join("bar/target").is_dir()); +} + +#[cargo_test] +fn test_path_dependency_under_member() { + let p = project() + .file( + "ws/Cargo.toml", + r#" + [package] + name = "ws" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + foo = { path = "../foo" } + + [workspace] + "#, + ) + .file("ws/src/lib.rs", "extern crate foo; pub fn f() { foo::f() }") + .file( + "foo/Cargo.toml", + r#" + [package] + workspace = "../ws" + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "./bar" } + "#, + ) + .file( + "foo/src/lib.rs", + "extern crate bar; pub fn f() { bar::f() }", + ) + .file("foo/bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("foo/bar/src/lib.rs", "pub fn f() { }"); + let p = p.build(); + + p.cargo("check").cwd("ws").run(); + + assert!(!p.root().join("foo/bar/Cargo.lock").is_file()); + assert!(!p.root().join("foo/bar/target").is_dir()); + + p.cargo("check").cwd("foo/bar").run(); + + assert!(!p.root().join("foo/bar/Cargo.lock").is_file()); + assert!(!p.root().join("foo/bar/target").is_dir()); +} + +#[cargo_test] +fn excluded_simple() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "ws" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + exclude = ["foo"] + "#, + ) + .file("src/lib.rs", "") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", ""); + let p = p.build(); + + p.cargo("check").run(); + assert!(p.root().join("target").is_dir()); + p.cargo("check").cwd("foo").run(); + assert!(p.root().join("foo/target").is_dir()); +} + +#[cargo_test] +fn exclude_members_preferred() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "ws" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["foo/bar"] + exclude = ["foo"] + "#, + ) + .file("src/lib.rs", "") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + .file("foo/bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("foo/bar/src/lib.rs", ""); + let p = p.build(); + + p.cargo("check").run(); + assert!(p.root().join("target").is_dir()); + p.cargo("check").cwd("foo").run(); + assert!(p.root().join("foo/target").is_dir()); + p.cargo("check").cwd("foo/bar").run(); + assert!(!p.root().join("foo/bar/target").is_dir()); +} + +#[cargo_test] +fn exclude_but_also_depend() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "ws" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "foo/bar" } + + [workspace] + exclude = ["foo"] + "#, + ) + .file("src/lib.rs", "") + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + .file("foo/bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("foo/bar/src/lib.rs", ""); + let p = p.build(); + + p.cargo("check").run(); + assert!(p.root().join("target").is_dir()); + p.cargo("check").cwd("foo").run(); + assert!(p.root().join("foo/target").is_dir()); + p.cargo("check").cwd("foo/bar").run(); + assert!(p.root().join("foo/bar/target").is_dir()); +} + +#[cargo_test] +fn excluded_default_members_still_must_be_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo"] + default-members = ["foo", "bar"] + exclude = ["bar"] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + .file("bar/something.txt", ""); + let p = p.build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package `[ROOT]/foo/bar` is listed in default-members but is not a member +for workspace at `[ROOT]/foo/Cargo.toml`. + +"#]]) + .run(); +} + +#[cargo_test] +fn excluded_default_members_crate_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar/*"] + default-members = ["bar/*"] + exclude = ["bar/quux"] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/main.rs", "fn main() {}") + .file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("bar/baz/src/main.rs", "fn main() {}") + .file("bar/quux/Cargo.toml", &basic_manifest("quux", "0.1.0")) + .file("bar/quux/src/main.rs", "fn main() {}"); + + let p = p.build(); + p.cargo("build").run(); + + assert!(p.root().join("target").is_dir()); + assert!(!p.bin("foo").is_file()); + assert!(p.bin("baz").is_file()); + assert!(!p.bin("quux").exists()); + + p.cargo("build --workspace").run(); + assert!(p.root().join("target").is_dir()); + assert!(p.bin("foo").is_file()); + assert!(!p.bin("quux").exists()); + + p.cargo("build").cwd("bar/quux").run(); + assert!(p.root().join("bar/quux/target").is_dir()); +} + +#[cargo_test] +fn excluded_default_members_not_crate_glob() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar/*"] + default-members = ["bar/*"] + exclude = ["bar/docs"] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/main.rs", "fn main() {}") + .file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("bar/baz/src/main.rs", "fn main() {}") + .file("bar/docs/readme.txt", "This folder is not a crate!"); + + let p = p.build(); + p.cargo("build").run(); + + assert!(!p.bin("foo").is_file()); + assert!(p.bin("baz").is_file()); + p.cargo("build --workspace").run(); + assert!(p.bin("foo").is_file()); +} + +#[cargo_test] +fn glob_syntax() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["crates/*"] + exclude = ["crates/qux"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "crates/bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../.." + "#, + ) + .file("crates/bar/src/main.rs", "fn main() {}") + .file( + "crates/baz/Cargo.toml", + r#" + [package] + name = "baz" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../.." + "#, + ) + .file("crates/baz/src/main.rs", "fn main() {}") + .file( + "crates/qux/Cargo.toml", + r#" + [package] + name = "qux" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file("crates/qux/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + assert!(!p.bin("bar").is_file()); + assert!(!p.bin("baz").is_file()); + + p.cargo("build").cwd("crates/bar").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + + p.cargo("build").cwd("crates/baz").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("baz").is_file()); + + p.cargo("build").cwd("crates/qux").run(); + assert!(!p.bin("qux").is_file()); + + assert!(p.root().join("Cargo.lock").is_file()); + assert!(!p.root().join("crates/bar/Cargo.lock").is_file()); + assert!(!p.root().join("crates/baz/Cargo.lock").is_file()); + assert!(p.root().join("crates/qux/Cargo.lock").is_file()); +} + +/*FIXME: This fails because of how workspace.exclude and workspace.members are working. +#[cargo_test] +fn glob_syntax_2() { + let p = project() + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["crates/b*"] + exclude = ["crates/q*"] + "#) + .file("src/main.rs", "fn main() {}") + .file("crates/bar/Cargo.toml", r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../.." + "#) + .file("crates/bar/src/main.rs", "fn main() {}") + .file("crates/baz/Cargo.toml", r#" + [package] + name = "baz" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = "../.." + "#) + .file("crates/baz/src/main.rs", "fn main() {}") + .file("crates/qux/Cargo.toml", r#" + [package] + name = "qux" + version = "0.1.0" + edition = "2015" + authors = [] + "#) + .file("crates/qux/src/main.rs", "fn main() {}"); + p.build(); + + p.cargo("build").run(); + assert!(p.bin("foo").is_file()); + assert!(!p.bin("bar").is_file()); + assert!(!p.bin("baz").is_file()); + + p.cargo("build").cwd("crates/bar").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("bar").is_file()); + + p.cargo("build").cwd("crates/baz").run(); + assert!(p.bin("foo").is_file()); + assert!(p.bin("baz").is_file()); + + p.cargo("build").cwd("crates/qux").run(); + assert!(!p.bin("qux").is_file()); + + assert!(p.root().join("Cargo.lock").is_file()); + assert!(!p.root().join("crates/bar/Cargo.lock").is_file()); + assert!(!p.root().join("crates/baz/Cargo.lock").is_file()); + assert!(p.root().join("crates/qux/Cargo.lock").is_file()); +} +*/ + +#[cargo_test] +fn glob_syntax_invalid_members() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["crates/*"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file("crates/bar/src/main.rs", "fn main() {}"); + let p = p.build(); + + p.cargo("check") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to load manifest for workspace member `[ROOT]/foo/crates/bar` +referenced via `crates/*` by workspace at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to read `[ROOT]/foo/crates/bar/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +/// This is a freshness test for feature use with workspaces. +/// +/// `feat_lib` is used by `caller1` and `caller2`, but with different features enabled. +/// This test ensures that alternating building `caller1`, `caller2` doesn't force +/// recompile of `feat_lib`. +/// +/// Ideally, once we solve rust-lang/cargo#3620, then a single Cargo build at the top level +/// will be enough. +#[cargo_test] +fn dep_used_with_separate_features() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["feat_lib", "caller1", "caller2"] + "#, + ) + .file( + "feat_lib/Cargo.toml", + r#" + [package] + name = "feat_lib" + version = "0.1.0" + edition = "2015" + authors = [] + + [features] + myfeature = [] + "#, + ) + .file("feat_lib/src/lib.rs", "") + .file( + "caller1/Cargo.toml", + r#" + [package] + name = "caller1" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + feat_lib = { path = "../feat_lib" } + "#, + ) + .file("caller1/src/main.rs", "fn main() {}") + .file("caller1/src/lib.rs", "") + .file( + "caller2/Cargo.toml", + r#" + [package] + name = "caller2" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + feat_lib = { path = "../feat_lib", features = ["myfeature"] } + caller1 = { path = "../caller1" } + "#, + ) + .file("caller2/src/main.rs", "fn main() {}") + .file("caller2/src/lib.rs", ""); + let p = p.build(); + + // Build the entire workspace. + p.cargo("build --workspace") + .with_stderr_data(str![[r#" +[COMPILING] feat_lib v0.1.0 ([ROOT]/foo/feat_lib) +[COMPILING] caller1 v0.1.0 ([ROOT]/foo/caller1) +[COMPILING] caller2 v0.1.0 ([ROOT]/foo/caller2) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + assert!(p.bin("caller1").is_file()); + assert!(p.bin("caller2").is_file()); + + // Build `caller1`. Should build the dep library. Because the features + // are different than the full workspace, it rebuilds. + // Ideally once we solve rust-lang/cargo#3620, then a single Cargo build at the top level + // will be enough. + p.cargo("build") + .cwd("caller1") + .with_stderr_data(str![[r#" +[COMPILING] feat_lib v0.1.0 ([ROOT]/foo/feat_lib) +[COMPILING] caller1 v0.1.0 ([ROOT]/foo/caller1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + + // Alternate building `caller2`/`caller1` a few times, just to make sure + // features are being built separately. Should not rebuild anything. + p.cargo("build") + .cwd("caller2") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .cwd("caller1") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); + p.cargo("build") + .cwd("caller2") + .with_stderr_data(str![[r#" +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]) + .run(); +} + +#[cargo_test] +fn dont_recurse_out_of_cargo_home() { + let git_project = git::new("dep", |project| { + project + .file("Cargo.toml", &basic_manifest("dep", "0.1.0")) + .file("src/lib.rs", "") + .file( + "build.rs", + r#" + use std::env; + use std::path::Path; + use std::process::{self, Command}; + + fn main() { + let cargo = env::var_os("CARGO").unwrap(); + let cargo_manifest_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); + let output = Command::new(cargo) + .args(&["metadata", "--format-version", "1", "--manifest-path"]) + .arg(&Path::new(&cargo_manifest_dir).join("Cargo.toml")) + .output() + .unwrap(); + if !output.status.success() { + eprintln!("{}", String::from_utf8(output.stderr).unwrap()); + process::exit(1); + } + } + "#, + ) + }); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies.dep] + git = "{}" + + [workspace] + "#, + git_project.url() + ), + ) + .file("src/lib.rs", ""); + let p = p.build(); + + p.cargo("check") + .env("CARGO_HOME", p.root().join(".cargo")) + .run(); +} + +// FIXME: this fails because of how workspace.exclude and workspace.members are working. +/* +#[cargo_test] +fn include_and_exclude() { + let p = project() + .file("Cargo.toml", r#" + [workspace] + members = ["foo"] + exclude = ["foo/bar"] + "#) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", "") + .file("foo/bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("foo/bar/src/lib.rs", ""); + p.build(); + + p.cargo("build").cwd("foo").run(); + assert!(p.root().join("target").is_dir()); + assert!(!p.root().join("foo/target").is_dir()); + p.cargo("build").cwd("foo/bar").run(); + assert!(p.root().join("foo/bar/target").is_dir()); +} +*/ + +#[cargo_test] +fn cargo_home_at_root_works() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["a"] + "#, + ) + .file("src/lib.rs", "") + .file("a/Cargo.toml", &basic_manifest("a", "0.1.0")) + .file("a/src/lib.rs", ""); + let p = p.build(); + + p.cargo("check").run(); + p.cargo("check --frozen").env("CARGO_HOME", p.root()).run(); +} + +#[cargo_test] +fn relative_rustc() { + let p = project() + .file( + "src/main.rs", + r#" + use std::process::Command; + use std::env; + + fn main() { + let mut cmd = Command::new("rustc"); + for arg in env::args_os().skip(1) { + cmd.arg(arg); + } + std::process::exit(cmd.status().unwrap().code().unwrap()); + } + "#, + ) + .build(); + p.cargo("build").run(); + + let src = p + .root() + .join("target/debug/foo") + .with_extension(env::consts::EXE_EXTENSION); + + Package::new("a", "0.1.0").publish(); + + let p = project() + .at("lib") + .file( + "Cargo.toml", + r#" + [package] + name = "lib" + version = "0.1.0" + edition = "2015" + + [dependencies] + a = "0.1" + "#, + ) + .file("src/lib.rs", "") + .build(); + + fs::copy(&src, p.root().join(src.file_name().unwrap())).unwrap(); + + let file = format!("./foo{}", env::consts::EXE_SUFFIX); + p.cargo("build").env("RUSTC", &file).run(); +} + +#[cargo_test] +fn ws_rustc_err() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("rustc") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] manifest path `[ROOT]/foo/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace + +"#]]) + .run(); + + p.cargo("rustdoc") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] manifest path `[ROOT]/foo/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace + +"#]]) + .run(); +} + +#[cargo_test] +fn ws_err_unused() { + for table in &[ + "[lib]", + "[[bin]]", + "[[example]]", + "[[test]]", + "[[bench]]", + "[dependencies]", + "[dev-dependencies]", + "[build-dependencies]", + "[features]", + "[target]", + "[badges]", + "[lints]", + ] { + let key = table.trim_start_matches('[').trim_end_matches(']'); + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [workspace] + members = ["a"] + + {table} + "#, + ), + ) + .file("a/Cargo.toml", &basic_lib_manifest("a")) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .with_status(101) + .with_stderr_data(&format!( + "\ +[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml` + +Caused by: + this virtual manifest specifies a `{key}` section, which is not allowed +", + )) + .run(); + } +} + +#[cargo_test] +fn ws_warn_unused() { + for (key, name) in &[ + ("[profile.dev]\nopt-level = 1", "profiles"), + ("[replace]\n\"bar:0.1.0\" = { path = \"bar\" }", "replace"), + ("[patch.crates-io]\nbar = { path = \"bar\" }", "patch"), + ] { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + &format!( + r#" + [package] + name = "a" + version = "0.1.0" + edition = "2015" + + {} + "#, + key + ), + ) + .file("a/src/lib.rs", "") + .build(); + p.cargo("check") + .with_stderr_data(&format!( + "\ +[WARNING] {} for the non root package will be ignored, specify {} at the workspace root: +package: [ROOT]/foo/a/Cargo.toml +workspace: [ROOT]/foo/Cargo.toml +[CHECKING] a v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +", + name, name + )) + .run(); + } +} + +#[cargo_test] +fn ws_warn_path() { + // Warnings include path to manifest. + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["a"] + "#, + ) + .file( + "a/Cargo.toml", + r#" + cargo-features = ["edition"] + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + "#, + ) + .file("a/src/lib.rs", "") + .build(); + + p.cargo("check").with_stderr_data(str![[r#" +[WARNING] [ROOT]/foo/a/Cargo.toml: the cargo feature `edition` has been stabilized in the 1.31 release and is no longer necessary to be listed in the manifest + See https://doc.rust-lang.org/cargo/reference/manifest.html#the-edition-field for more information about using this feature. +[CHECKING] foo v0.1.0 ([ROOT]/foo/a) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]]).run(); +} + +#[cargo_test] +fn invalid_missing() { + // Make sure errors are not suppressed with -q. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [dependencies] + x = { path = 'x' } + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("check -q") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to get `x` as a dependency of package `foo v0.1.0 ([ROOT]/foo)` + +Caused by: + failed to load source for dependency `x` + +Caused by: + Unable to update [ROOT]/foo/x + +Caused by: + failed to read `[ROOT]/foo/x/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn member_dep_missing() { + // Make sure errors are not suppressed with -q. + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + + [workspace] + members = ["bar"] + "#, + ) + .file("src/main.rs", "fn main() {}") + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + + [dependencies] + baz = { path = "baz" } + "#, + ) + .file("bar/src/main.rs", "fn main() {}") + .build(); + + p.cargo("check -q") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] failed to load manifest for workspace member `[ROOT]/foo/bar` +referenced by workspace at `[ROOT]/foo/Cargo.toml` + +Caused by: + failed to load manifest for dependency `baz` + +Caused by: + failed to read `[ROOT]/foo/bar/baz/Cargo.toml` + +Caused by: + [NOT_FOUND] + +"#]]) + .run(); +} + +#[cargo_test] +fn simple_primary_package_env_var() { + let is_primary_package = r#" + #[test] + fn verify_primary_package() {{ + assert!(option_env!("CARGO_PRIMARY_PACKAGE").is_some()); + }} + "#; + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [workspace] + members = ["bar"] + "#, + ) + .file("src/lib.rs", is_primary_package) + .file( + "bar/Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + workspace = ".." + "#, + ) + .file("bar/src/lib.rs", is_primary_package); + let p = p.build(); + + p.cargo("test").run(); + + // Again, this time selecting a specific crate + p.cargo("clean").run(); + p.cargo("test -p bar").run(); + + // Again, this time selecting all crates + p.cargo("clean").run(); + p.cargo("test --all").run(); +} + +#[cargo_test] +fn virtual_primary_package_env_var() { + let is_primary_package = r#" + #[test] + fn verify_primary_package() {{ + assert!(option_env!("CARGO_PRIMARY_PACKAGE").is_some()); + }} + "#; + + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + members = ["foo", "bar"] + "#, + ) + .file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0")) + .file("foo/src/lib.rs", is_primary_package) + .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("bar/src/lib.rs", is_primary_package); + let p = p.build(); + + p.cargo("test").run(); + + // Again, this time selecting a specific crate + p.cargo("clean").run(); + p.cargo("test -p foo").run(); +} + +#[cargo_test] +fn ensure_correct_workspace_when_nested() { + let p = project() + .file( + "Cargo.toml", + r#" + [workspace] + + [package] + name = "bar" + version = "0.1.0" + edition = "2015" + authors = [] + "#, + ) + .file("src/lib.rs", "") + .file( + "sub/Cargo.toml", + r#" + [workspace] + members = ["foo"] + "#, + ) + .file( + "sub/foo/Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2015" + authors = [] + + [dependencies] + bar = { path = "../.."} + "#, + ) + .file("sub/foo/src/main.rs", "fn main() {}"); + let p = p.build(); + p.cargo("tree") + .cwd("sub/foo") + .with_stdout_data(str![[r#" +foo v0.1.0 ([ROOT]/foo/sub/foo) +└── bar v0.1.0 ([ROOT]/foo) + +"#]]) + .run(); +} + +#[cargo_test] +fn nonexistence_package_togother_with_workspace() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + edition = "2021" + + [workspace] + members = ["baz"] + "#, + ) + .file("src/lib.rs", "") + .file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0")) + .file("baz/src/lib.rs", ""); + + let p = p.build(); + + p.cargo("check --package nonexistence --workspace") + .with_status(101) + .with_stderr_data( + str![[r#" +[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo` + +"#]] + .unordered(), + ) + .run(); + // With pattern * + p.cargo("check --package nonpattern* --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo` + +"#]]) + .run(); + + p.cargo("package --package nonexistence --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo` + +"#]]) + .run(); + // With pattern * + p.cargo("package --package nonpattern* --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo` + +"#]]) + .run(); + + p.cargo("publish --dry-run --package nonexistence -Zpackage-workspace --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo` + +"#]]) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .run(); + // With pattern * + p.cargo("publish --dry-run --package nonpattern* -Zpackage-workspace --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo` + +"#]]) + .masquerade_as_nightly_cargo(&["package-workspace"]) + .run(); + + p.cargo("tree --package nonexistence --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package(s) `nonexistence` not found in workspace `[ROOT]/foo` + +"#]]) + .run(); + // With pattern * + p.cargo("tree --package nonpattern* --workspace") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] package pattern(s) `nonpattern*` not found in workspace `[ROOT]/foo` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/yank.rs b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/yank.rs new file mode 100644 index 000000000..04967a7a3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/tests/testsuite/yank.rs @@ -0,0 +1,214 @@ +//! Tests for the `cargo yank` command. + +use std::fs; + +use cargo_test_support::prelude::*; +use cargo_test_support::project; +use cargo_test_support::registry; +use cargo_test_support::str; + +fn setup(name: &str, version: &str) { + let dir = registry::api_path().join(format!("api/v1/crates/{}/{}", name, version)); + dir.mkdir_p(); + fs::write(dir.join("yank"), r#"{"ok": true}"#).unwrap(); +} + +#[cargo_test] +fn explicit_version() { + let registry = registry::init(); + setup("foo", "0.0.1"); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("yank --version 0.0.1") + .replace_crates_io(registry.index_url()) + .run(); + + p.cargo("yank --undo --version 0.0.1") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index + Unyank foo@0.0.1 +[ERROR] failed to undo a yank from the registry at [ROOTURL]/api + +Caused by: + EOF while parsing a value at line 1 column 0 + +"#]]) + .run(); +} + +#[cargo_test] +fn explicit_version_with_asymmetric() { + let registry = registry::RegistryBuilder::new() + .http_api() + .token(cargo_test_support::registry::Token::rfc_key()) + .build(); + setup("foo", "0.0.1"); + + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + // 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("-Zasymmetric-token") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .replace_crates_io(registry.index_url()) + .run(); + + p.cargo("yank --undo --version 0.0.1") + .arg("-Zasymmetric-token") + .masquerade_as_nightly_cargo(&["asymmetric-token"]) + .replace_crates_io(registry.index_url()) + .run(); +} + +#[cargo_test] +fn inline_version() { + let registry = registry::init(); + setup("foo", "0.0.1"); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("yank foo@0.0.1") + .replace_crates_io(registry.index_url()) + .run(); + + p.cargo("yank --undo foo@0.0.1") + .replace_crates_io(registry.index_url()) + .with_status(101) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index + Unyank foo@0.0.1 +[ERROR] failed to undo a yank from the registry at [ROOTURL]/api + +Caused by: + EOF while parsing a value at line 1 column 0 + +"#]]) + .run(); +} + +#[cargo_test] +fn version_required() { + setup("foo", "0.0.1"); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("yank foo") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] `--version` is required + +"#]]) + .run(); +} + +#[cargo_test] +fn inline_version_without_name() { + setup("foo", "0.0.1"); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("yank @0.0.1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] missing crate name for `@0.0.1` + +"#]]) + .run(); +} + +#[cargo_test] +fn inline_and_explicit_version() { + setup("foo", "0.0.1"); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + license = "MIT" + description = "foo" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("yank foo@0.0.1 --version 0.0.1") + .with_status(101) + .with_stderr_data(str![[r#" +[ERROR] cannot specify both `@0.0.1` and `--version` + +"#]]) + .run(); +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/triagebot.toml b/collector/compile-benchmarks/cargo-0.87.1/triagebot.toml new file mode 100644 index 000000000..196c7ee60 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/triagebot.toml @@ -0,0 +1,363 @@ +[relabel] +allow-unauthenticated = [ + "A-*", + "C-*", + "Command-*", + "E-*", + "I-*", + "O-*", + "S-*", + "Z-*", + "beta-nominated", + "regression-*", + "relnotes", +] + +[ping.windows] +message = """\ +Hey Windows Group! This bug has been identified as a good "Windows candidate". +In case it's useful, here are some [instructions] for tackling these sorts of +bugs. Maybe take a look? +Thanks! <3 + +[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/windows.html +""" +label = "O-windows" + +[shortcut] + +[transfer] + +[merge-conflicts] +remove = [] +add = ["S-waiting-on-author"] +unless = ["S-blocked", "S-waiting-on-review"] + +[autolabel."S-waiting-on-review"] +new_pr = true + +[assign] +contributing_url = "https://rust-lang.github.io/cargo/contrib/" +warn_non_default_branch = true + +[assign.owners] +"*" = ["@ehuss", "@epage", "@weihanglo"] + + +[review-submitted] +reviewed_label = "S-waiting-on-author" +review_labels = ["S-waiting-on-review"] + +[review-requested] +remove_labels = ["S-waiting-on-author"] +add_labels = ["S-waiting-on-review"] + +[autolabel."A-build-execution"] +trigger_files = [ + "src/cargo/core/compiler/compilation.rs", + "src/cargo/core/compiler/job_queue/", + "src/cargo/core/compiler/mod.rs", +] + +[autolabel."A-build-scripts"] +trigger_files = [ + "crates/build-rs-test-lib/", + "crates/build-rs/", + "src/cargo/core/compiler/custom_build.rs", +] + +[autolabel."A-cache-messages"] +trigger_files = ["src/cargo/util/rustc.rs"] + +[autolabel."A-cargo-targets"] +trigger_files = [ + "src/cargo/ops/cargo_compile/compile_filter.rs", + "src/cargo/ops/cargo_compile/unit_generator.rs", +] + +[autolabel."A-cfg-expr"] +trigger_files = [ + "crates/cargo-platform/", + "src/cargo/core/compiler/build_context/target_info.rs", +] + +[autolabel."A-cli"] +trigger_files = ["src/bin/", "src/cargo/util/command_prelude.rs"] + +[autolabel."A-cli-help"] +trigger_files = ["crates/mdman/", "src/etc/man/"] + +[autolabel."A-completions"] +trigger_files = ["src/etc/_cargo", "src/etc/cargo.bashcomp.sh"] + +[autolabel."A-configuration"] +trigger_files = ["src/cargo/util/context/mod.rs"] + +[autolabel."A-console-output"] +trigger_files = [ + "src/cargo/core/shell.rs", + "src/cargo/util/machine_message.rs", + "src/cargo/util/progress.rs", +] + +[autolabel."A-crate-dependencies"] +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"] + +[autolabel."A-dependency-resolution"] +trigger_files = [ + "benches/benchsuite/benches/resolve.rs", + "crates/resolver-tests/", + "src/cargo/core/resolver/", +] + +[autolabel."A-directory-source"] +trigger_files = ["src/cargo/sources/directory.rs"] + +[autolabel."A-documenting-cargo-itself"] +trigger_files = ["src/doc/"] + +[autolabel."A-environment-variables"] +trigger_files = [ + "crates/home/", + "src/cargo/util/context/environment.rs", +] + +[autolabel."A-features2"] +trigger_files = ["src/cargo/core/resolver/features.rs"] + +[autolabel."A-filesystem"] +trigger_files = ["src/cargo/util/flock.rs", "src/cargo/util/important_paths.rs"] + +[autolabel."A-future-incompat"] +trigger_files = ["src/cargo/core/compiler/future_incompat.rs"] + +[autolabel."A-git"] +trigger_files = ["src/cargo/sources/git/", "src/cargo/ops/cargo_package/vcs.rs"] + +[autolabel."A-home"] +trigger_files = ["crates/home/"] + +[autolabel."A-infrastructure"] +trigger_files = [ + ".cargo/", + ".github/", + "build.rs", + "ci/", + "clippy.toml", + "crates/xtask-", + "deny.toml", + "publish.py", + "triagebot.toml", +] + +[autolabel."A-interacts-with-crates.io"] +trigger_files = ["crates/crates-io/", "src/cargo/ops/registry/"] + +[autolabel."A-layout"] +trigger_files = [ + "src/cargo/core/compiler/build_runner/compilation_files.rs", + "src/cargo/core/compiler/layout.rs", +] + +[autolabel."A-links"] +trigger_files = ["src/cargo/core/compiler/links.rs"] + +[autolabel."A-local-registry-source"] +trigger_files = ["src/cargo/sources/registry/local.rs"] + +[autolabel."A-lockfile"] +trigger_files = ["src/cargo/ops/lockfile.rs", "src/cargo/core/resolver/encode.rs"] + +[autolabel."A-lto"] +trigger_files = ["src/cargo/core/compiler/lto.rs"] + +[autolabel."A-manifest"] +trigger_files = [ + "crates/cargo-util-schemas/src/manifest/", + "src/cargo/core/manifest.rs", + "src/cargo/util/toml/mod.rs", + "src/cargo/util/toml_mut/", +] + +[autolabel."A-networking"] +trigger_files = ["src/cargo/util/network/"] + +[autolabel."A-overrides"] +trigger_files = ["src/cargo/sources/replaced.rs"] + +[autolabel."A-profiles"] +trigger_files = ["src/cargo/core/profiles.rs"] + +[autolabel."A-rebuild-detection"] +trigger_files = ["src/cargo/core/compiler/fingerprint/"] + +[autolabel."A-registries"] +trigger_files = ["src/cargo/sources/registry/", "src/cargo/core/registry.rs"] + +[autolabel."A-registry-authentication"] +trigger_files = ["src/cargo/util/auth/"] + +[autolabel."A-semver"] +trigger_files = [ + "crates/semver-check", + "src/cargo/util/semver_ext.rs", +] + +[autolabel."A-source-replacement"] +trigger_files = ["src/cargo/sources/replaced.rs"] + +[autolabel."A-sparse-registry"] +trigger_files = ["src/cargo/sources/registry/http_remote.rs"] + +[autolabel."A-testing-cargo-itself"] +trigger_files = [ + "benches/", + "crates/cargo-test-macro/", + "crates/cargo-test-support/", +] + +[autolabel."A-timings"] +trigger_files = [ + "src/cargo/core/compiler/timings.js", + "src/cargo/core/compiler/timings.rs", + "src/cargo/util/cpu.rs", +] + +[autolabel."A-unstable"] +trigger_files = ["src/cargo/core/features.rs"] + +[autolabel."A-vcs"] +trigger_files = ["src/cargo/util/vcs.rs"] + +[autolabel."A-workspaces"] +trigger_files = [ + "benches/benchsuite/benches/workspace_initialization.rs", + "src/cargo/core/workspace.rs", + "src/cargo/util/workspace.rs" +] + +[autolabel."Command-add"] +trigger_files = ["src/bin/cargo/commands/add.rs", "src/cargo/ops/cargo_add/"] + +[autolabel."Command-bench"] +trigger_files = ["src/bin/cargo/commands/bench.rs"] + +[autolabel."Command-build"] +trigger_files = ["src/bin/cargo/commands/build.rs"] + +[autolabel."Command-check"] +trigger_files = ["src/bin/cargo/commands/check.rs"] + +[autolabel."Command-clean"] +trigger_files = ["src/bin/cargo/commands/clean.rs", "src/cargo/ops/cargo_clean.rs"] + +[autolabel."Command-doc"] +trigger_files = ["src/bin/cargo/commands/doc.rs", "src/cargo/ops/cargo_doc.rs"] + +[autolabel."Command-fetch"] +trigger_files = ["src/bin/cargo/commands/fetch.rs", "src/cargo/ops/cargo_fetch.rs"] + +[autolabel."Command-fix"] +trigger_files = [ + "crates/rustfix/", + "src/bin/cargo/commands/fix.rs", + "src/cargo/ops/fix.rs", + "src/cargo/util/diagnostic_server.rs", + "src/cargo/util/lockserver.rs", +] + +[autolabel."Command-generate-lockfile"] +trigger_files = ["src/bin/cargo/commands/generate_lockfile.rs"] + +[autolabel."Command-git-checkout"] +trigger_files = ["src/bin/cargo/commands/git_checkout.rs"] + +[autolabel."Command-info"] +trigger_files = ["src/bin/cargo/commands/info.rs", "src/cargo/ops/registry/info/"] + +[autolabel."Command-init"] +trigger_files = ["src/bin/cargo/commands/init.rs"] + +[autolabel."Command-install"] +trigger_files = ["src/bin/cargo/commands/install.rs", "src/cargo/ops/cargo_install.rs"] + +[autolabel."Command-locate-project"] +trigger_files = ["src/bin/cargo/commands/locate_project.rs"] + +[autolabel."Command-login"] +trigger_files = ["src/bin/cargo/commands/login.rs", "src/cargo/ops/registry/login.rs"] + +[autolabel."Command-logout"] +trigger_files = ["src/bin/cargo/commands/logout.rs", "src/cargo/ops/registry/logout.rs"] + +[autolabel."Command-metadata"] +trigger_files = ["src/bin/cargo/commands/metadata.rs", "src/cargo/ops/cargo_output_metadata.rs"] + +[autolabel."Command-new"] +trigger_files = ["src/bin/cargo/commands/new.rs", "src/cargo/ops/cargo_new.rs"] + +[autolabel."Command-owner"] +trigger_files = ["src/bin/cargo/commands/owner.rs", "src/cargo/ops/registry/owner.rs"] + +[autolabel."Command-package"] +trigger_files = ["src/bin/cargo/commands/package.rs", "src/cargo/ops/cargo_package/"] + +[autolabel."Command-pkgid"] +trigger_files = ["src/bin/cargo/commands/pkgid.rs", "src/cargo/ops/cargo_pkgid.rs"] + +[autolabel."Command-publish"] +trigger_files = ["src/bin/cargo/commands/publish.rs", "src/cargo/ops/registry/publish.rs"] + +[autolabel."Command-read-manifest"] +trigger_files = ["src/bin/cargo/commands/read_manifest.rs", "src/cargo/ops/cargo_read_manifest.rs"] + +[autolabel."Command-remove"] +trigger_files = ["src/bin/cargo/commands/remove.rs", "src/cargo/ops/cargo_remove.rs"] + +[autolabel."Command-report"] +trigger_files = ["src/bin/cargo/commands/report.rs"] + +[autolabel."Command-run"] +trigger_files = ["src/bin/cargo/commands/run.rs", "src/cargo/ops/cargo_run.rs"] + +[autolabel."Command-rustc"] +trigger_files = ["src/bin/cargo/commands/rustc.rs"] + +[autolabel."Command-rustdoc"] +trigger_files = ["src/bin/cargo/commands/rustdoc.rs"] + +[autolabel."Command-search"] +trigger_files = ["src/bin/cargo/commands/search.rs", "src/cargo/ops/registry/search.rs"] + +[autolabel."Command-test"] +trigger_files = ["src/bin/cargo/commands/test.rs", "src/cargo/ops/cargo_test.rs"] + +[autolabel."Command-tree"] +trigger_files = ["src/bin/cargo/commands/tree.rs", "src/cargo/ops/tree/"] + +[autolabel."Command-uninstall"] +trigger_files = ["src/bin/cargo/commands/uninstall.rs", "src/cargo/ops/cargo_uninstall.rs"] + +[autolabel."Command-update"] +trigger_files = ["src/bin/cargo/commands/update.rs", "src/cargo/ops/cargo_update.rs"] + +[autolabel."Command-vendor"] +trigger_files = ["src/bin/cargo/commands/vendor.rs", "src/cargo/ops/vendor.rs"] + +[autolabel."Command-verify-project"] +trigger_files = ["src/bin/cargo/commands/verify_project.rs"] + +[autolabel."Command-version"] +trigger_files = ["src/bin/cargo/commands/version.rs"] + +[autolabel."Command-yank"] +trigger_files = ["src/bin/cargo/commands/yank.rs", "src/cargo/ops/registry/yank.rs"] diff --git a/collector/compile-benchmarks/cargo-0.87.1/windows.manifest.xml b/collector/compile-benchmarks/cargo-0.87.1/windows.manifest.xml new file mode 100644 index 000000000..8a9d5d1b7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/windows.manifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + UTF-8 + + + + + + true + + + From 44daca6d81a5873372d0733ba90b8d74dc726f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 15 Apr 2025 09:19:00 +0200 Subject: [PATCH 2/5] Add benchmark files and update documentation --- collector/compile-benchmarks/README.md | 2 ++ collector/compile-benchmarks/REUSE.toml | 5 +++++ .../compile-benchmarks/cargo-0.87.1/0-println.patch | 12 ++++++++++++ collector/compile-benchmarks/cargo-0.87.1/Cargo.toml | 2 ++ 4 files changed, 21 insertions(+) create mode 100644 collector/compile-benchmarks/cargo-0.87.1/0-println.patch diff --git a/collector/compile-benchmarks/README.md b/collector/compile-benchmarks/README.md index 4a68345a6..cd94bb5e7 100644 --- a/collector/compile-benchmarks/README.md +++ b/collector/compile-benchmarks/README.md @@ -23,6 +23,8 @@ They mostly consist of real-world crates. `N` value from 1 to 1024. - **cargo-0.60.0**: The Rust package manager. A large program, and an important part of the Rust ecosystem. +- **cargo-0.87.1**: The Rust package manager. A large program, and an important + part of the Rust ecosystem. - **clap-3.1.6**: A command line argument parser library. A crate used by many Rust programs. - **cranelift-codegen-0.82.1**: The largest crate from a code generator. Used by diff --git a/collector/compile-benchmarks/REUSE.toml b/collector/compile-benchmarks/REUSE.toml index 450f2ac81..12db291dd 100644 --- a/collector/compile-benchmarks/REUSE.toml +++ b/collector/compile-benchmarks/REUSE.toml @@ -32,6 +32,11 @@ path = "cargo-0.60.0/**" SPDX-FileCopyrightText = "The Rust Project Developers (see https://thanks.rust-lang.org)" SPDX-License-Identifier = "MIT OR Apache-2.0" +[[annotations]] +path = "cargo-0.87.1/**" +SPDX-FileCopyrightText = "The Rust Project Developers (see https://thanks.rust-lang.org)" +SPDX-License-Identifier = "MIT OR Apache-2.0" + [[annotations]] path = "clap-3.1.6/**" SPDX-FileCopyrightText = "clap contributors" diff --git a/collector/compile-benchmarks/cargo-0.87.1/0-println.patch b/collector/compile-benchmarks/cargo-0.87.1/0-println.patch new file mode 100644 index 000000000..26e356c13 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/0-println.patch @@ -0,0 +1,12 @@ +diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs +index c1e81528..7ae91667 100644 +--- a/src/cargo/sources/path.rs ++++ b/src/cargo/sources/path.rs +@@ -58,6 +58,7 @@ impl<'gctx> PathSource<'gctx> { + /// Preloads a package for this source. The source is assumed that it has + /// yet loaded any other packages. + pub fn preload_with(pkg: Package, gctx: &'gctx GlobalContext) -> Self { ++ println!("testing"); + let source_id = pkg.package_id().source_id(); + let path = pkg.root().to_owned(); + Self { diff --git a/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml b/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml index 65a7b97a0..5fd7f82f0 100644 --- a/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml +++ b/collector/compile-benchmarks/cargo-0.87.1/Cargo.toml @@ -393,3 +393,5 @@ rust_2018_idioms = "warn" [lints.rustdoc] private_intra_doc_links = "allow" + +[workspace] From 4f766fe2b3fa7b642f6b55de723ad371620f9fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 15 Apr 2025 10:01:55 +0200 Subject: [PATCH 3/5] Split cargo on CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c5ba3653..27e7b6444 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,8 +114,8 @@ jobs: # # We want the four parts to have similar runtimes. BENCH_INCLUDE_EXCLUDE_OPTS: [ - "--include cargo-0.60.0,stm32f4-0.14.0,webrender-2022", - "--exclude cargo-0.60.0,stm32f4-0.14.0,webrender-2022", + "--include cargo-0.60.0,cargo-0.87.1,stm32f4-0.14.0,webrender-2022", + "--exclude cargo-0.60.0,cargo-0.87.1,stm32f4-0.14.0,webrender-2022", ] PROFILES: [ "Check,Debug,Doc", From ef7d055bf7f36dc3270fac5d413aadced2917dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 15 Apr 2025 12:58:37 +0200 Subject: [PATCH 4/5] Improve error message when Cargo.lock is missing --- collector/src/compile/execute/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/collector/src/compile/execute/mod.rs b/collector/src/compile/execute/mod.rs index 004a05c49..9a20dd7cd 100644 --- a/collector/src/compile/execute/mod.rs +++ b/collector/src/compile/execute/mod.rs @@ -290,9 +290,10 @@ impl<'a> CargoProcess<'a> { let _guard = EnsureImmutableFile::new( &self.cwd.join("Cargo.lock"), self.processor_name.0.clone(), - )?; + ) + .context("cannot resolve Cargo.lock")?; - // Get the subcommand. If it's not `rustc` it must should be a + // Get the subcommand. If it's not `rustc` it should be a // subcommand that itself invokes `rustc` (so that the `FAKE_RUSTC` // machinery works). let cargo_subcommand = From 1c5c55ff8cd10ff6d8f1e6a40c3dc37c15a56aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 15 Apr 2025 13:03:00 +0200 Subject: [PATCH 5/5] Add missing Cargo.lock --- .../cargo-0.87.1/Cargo.lock | 3964 +++++++++++++++++ 1 file changed, 3964 insertions(+) create mode 100644 collector/compile-benchmarks/cargo-0.87.1/Cargo.lock diff --git a/collector/compile-benchmarks/cargo-0.87.1/Cargo.lock b/collector/compile-benchmarks/cargo-0.87.1/Cargo.lock new file mode 100644 index 000000000..df4ca9e26 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/Cargo.lock @@ -0,0 +1,3964 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy 0.7.35", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "annotate-snippets" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +dependencies = [ + "anstyle", + "unicode-width", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-lossy" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934ff8719effd2023a48cf63e69536c1c3ced9d3895068f6f5cc9a4ff845e59b" +dependencies = [ + "anstyle", +] + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-svg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3607949e9f6de49ea4bafe12f5e4fd73613ebf24795e48587302a8cc0e4bb35" +dependencies = [ + "anstream", + "anstyle", + "anstyle-lossy", + "html-escape", + "unicode-width", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "blake3" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +dependencies = [ + "memchr", + "regex-automata 0.4.9", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" + +[[package]] +name = "bytesize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" + +[[package]] +name = "cargo" +version = "0.87.1" +dependencies = [ + "annotate-snippets", + "anstream", + "anstyle", + "anyhow", + "base64", + "blake3", + "bytesize", + "cargo-credential", + "cargo-credential-libsecret", + "cargo-credential-macos-keychain", + "cargo-credential-wincred", + "cargo-platform", + "cargo-test-support", + "cargo-util", + "cargo-util-schemas", + "clap", + "clap_complete", + "color-print", + "crates-io", + "curl", + "curl-sys", + "filetime", + "flate2", + "git2", + "git2-curl", + "gix", + "glob", + "hex", + "hmac", + "home", + "http-auth", + "humantime", + "ignore", + "im-rc", + "indexmap", + "itertools", + "jobserver", + "lazycell", + "libc", + "libgit2-sys", + "memchr", + "opener", + "openssl", + "openssl-sys", + "os_info", + "pasetors", + "pathdiff", + "rand", + "regex", + "rusqlite", + "rustc-hash", + "rustc-stable-hash", + "rustfix", + "same-file", + "semver", + "serde", + "serde-untagged", + "serde_ignored", + "serde_json", + "sha1", + "shell-escape", + "snapbox", + "supports-hyperlinks", + "supports-unicode", + "tar", + "tempfile", + "thiserror 2.0.11", + "time", + "toml", + "toml_edit", + "tracing", + "tracing-chrome", + "tracing-subscriber", + "unicase", + "unicode-width", + "url", + "walkdir", + "windows-sys 0.59.0", +] + +[[package]] +name = "cargo-credential" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1ef5080adde1db190e901884d2c400990856c2a23201c5a181b910a6dbdf2a" +dependencies = [ + "anyhow", + "libc", + "serde", + "serde_json", + "thiserror 1.0.69", + "time", + "windows-sys 0.59.0", +] + +[[package]] +name = "cargo-credential-libsecret" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d8dbc26ce815b430803e756f6ad5f70a67d47bfcde9ca6f4276732c39551b8" +dependencies = [ + "anyhow", + "cargo-credential", + "libloading", +] + +[[package]] +name = "cargo-credential-macos-keychain" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b489cbdae63be32c040b5fe81b0f7725e563bcd805bb828e746971a4967aaf28" +dependencies = [ + "cargo-credential", + "security-framework", +] + +[[package]] +name = "cargo-credential-wincred" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49c6cb2255a5267a4d18077bc436db5a2c261d97a3dcbc84ccd9747b473b2f4b" +dependencies = [ + "cargo-credential", + "windows-sys 0.59.0", +] + +[[package]] +name = "cargo-platform" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-test-macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b48a3283d47bbf868fb375979f02d4701c2f61f0620493711d2f0e4bbc3d87" + +[[package]] +name = "cargo-test-support" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a414afc2c468d4bedfd3ef3ae677e88e4de06959a82ca25c9a6c79e0e83c041" +dependencies = [ + "anstream", + "anstyle", + "anyhow", + "cargo-test-macro", + "cargo-util", + "crates-io", + "filetime", + "flate2", + "git2", + "glob", + "itertools", + "pasetors", + "regex", + "serde", + "serde_json", + "snapbox", + "tar", + "time", + "toml", + "url", + "walkdir", + "windows-sys 0.59.0", +] + +[[package]] +name = "cargo-util" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527f6e2a4e80492e90628052be879a5996c2453ad5ec745bfa310a80b7eca20a" +dependencies = [ + "anyhow", + "core-foundation", + "filetime", + "hex", + "ignore", + "jobserver", + "libc", + "miow", + "same-file", + "sha2", + "shell-escape", + "tempfile", + "tracing", + "walkdir", + "windows-sys 0.59.0", +] + +[[package]] +name = "cargo-util-schemas" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e788664537bc508c6f252ca8b0e64275d89ca3ce11aeb71452a3554f390e3a65" +dependencies = [ + "semver", + "serde", + "serde-untagged", + "serde-value", + "thiserror 2.0.11", + "toml", + "unicode-xid", + "url", +] + +[[package]] +name = "cc" +version = "1.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.5.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375f9d8255adeeedd51053574fd8d4ba875ea5fa558e86617b07f09f1680c8b6" +dependencies = [ + "clap", + "clap_lex", + "is_executable", + "shlex", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "clru" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" + +[[package]] +name = "color-print" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aa954171903797d5623e047d9ab69d91b493657917bdfb8c2c80ecaf9cdb6f4" +dependencies = [ + "color-print-proc-macro", +] + +[[package]] +name = "color-print-proc-macro" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692186b5ebe54007e45a59aea47ece9eb4108e141326c304cdc91699a7118a22" +dependencies = [ + "nom", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "content_inspector" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" +dependencies = [ + "memchr", +] + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crates-io" +version = "0.40.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6967b9fa81bc485cf87748fdc2f8c79b922f5c59fe4f7c160329cee7fae4a314" +dependencies = [ + "curl", + "percent-encoding", + "serde", + "serde_json", + "thiserror 2.0.11", + "url", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ct-codecs" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b916ba8ce9e4182696896f015e8a5ae6081b305f74690baa8465e35f5a142ea4" + +[[package]] +name = "curl" +version = "0.4.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "curl-sys" +version = "0.4.79+curl-8.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a9bbeeb3996717ef1248018db20d1b0b5ba7165bff60e3b5135b4f4c2b37a5" +dependencies = [ + "cc", + "libc", + "libnghttp2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "windows-sys 0.52.0", +] + +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519-compact" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9b3460f44bea8cd47f45a0c70892f1eff856d97cd55358b2f73f663789f6190" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +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.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" +dependencies = [ + "serde", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + +[[package]] +name = "faster-hex" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" +dependencies = [ + "serde", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "libz-sys", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "git2" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fda788993cc341f69012feba8bf45c0ba4f3291fcc08e214b4d5a7332d88aff" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + +[[package]] +name = "git2-curl" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8dcabbc09ece4d30a9aa983d5804203b7e2f8054a171f792deff59b56d31fa" +dependencies = [ + "curl", + "git2", + "log", + "url", +] + +[[package]] +name = "gix" +version = "0.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736f14636705f3a56ea52b553e67282519418d9a35bb1e90b3a9637a00296b68" +dependencies = [ + "gix-actor", + "gix-attributes", + "gix-command", + "gix-commitgraph", + "gix-config", + "gix-credentials", + "gix-date", + "gix-diff", + "gix-dir", + "gix-discover", + "gix-features", + "gix-filter", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-hashtable", + "gix-ignore", + "gix-index", + "gix-lock", + "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-shallow", + "gix-submodule", + "gix-tempfile", + "gix-trace", + "gix-transport", + "gix-traverse", + "gix-url", + "gix-utils", + "gix-validate", + "gix-worktree", + "once_cell", + "prodash", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-actor" +version = "0.33.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20018a1a6332e065f1fcc8305c1c932c6b8c9985edea2284b3c79dc6fa3ee4b2" +dependencies = [ + "bstr", + "gix-date", + "gix-utils", + "itoa", + "thiserror 2.0.11", + "winnow 0.6.26", +] + +[[package]] +name = "gix-attributes" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f151000bf662ef5f641eca6102d942ee31ace80f271a3ef642e99776ce6ddb38" +dependencies = [ + "bstr", + "gix-glob", + "gix-path", + "gix-quote", + "gix-trace", + "kstring", + "smallvec", + "thiserror 2.0.11", + "unicode-bom", +] + +[[package]] +name = "gix-bitmap" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1db9765c69502650da68f0804e3dc2b5f8ccc6a2d104ca6c85bc40700d37540" +dependencies = [ + "thiserror 2.0.11", +] + +[[package]] +name = "gix-chunk" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b1f1d8764958699dc764e3f727cef280ff4d1bd92c107bbf8acd85b30c1bd6f" +dependencies = [ + "thiserror 2.0.11", +] + +[[package]] +name = "gix-command" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb410b84d6575db45e62025a9118bdbf4d4b099ce7575a76161e898d9ca98df1" +dependencies = [ + "bstr", + "gix-path", + "gix-trace", + "shell-words", +] + +[[package]] +name = "gix-commitgraph" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e23a8ec2d8a16026a10dafdb6ed51bcfd08f5d97f20fa52e200bc50cb72e4877" +dependencies = [ + "bstr", + "gix-chunk", + "gix-features", + "gix-hash", + "memmap2", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-config" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "377c1efd2014d5d469e0b3cd2952c8097bce9828f634e04d5665383249f1d9e9" +dependencies = [ + "bstr", + "gix-config-value", + "gix-features", + "gix-glob", + "gix-path", + "gix-ref", + "gix-sec", + "memchr", + "once_cell", + "smallvec", + "thiserror 2.0.11", + "unicode-bom", + "winnow 0.6.26", +] + +[[package]] +name = "gix-config-value" +version = "0.14.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11365144ef93082f3403471dbaa94cfe4b5e72743bdb9560719a251d439f4cee" +dependencies = [ + "bitflags", + "bstr", + "gix-path", + "libc", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-credentials" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf950f9ee1690bb9c4388b5152baa8a9f41ad61e5cf1ba0ec8c207b08dab9e45" +dependencies = [ + "bstr", + "gix-command", + "gix-config-value", + "gix-path", + "gix-prompt", + "gix-sec", + "gix-trace", + "gix-url", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-date" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c57c477b645ee248b173bb1176b52dd528872f12c50375801a58aaf5ae91113f" +dependencies = [ + "bstr", + "itoa", + "jiff", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-diff" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62afb7f4ca0acdf4e9dad92065b2eb1bf2993bcc5014b57bc796e3a365b17c4d" +dependencies = [ + "bstr", + "gix-hash", + "gix-object", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-dir" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d78db3927a12f7d1b788047b84efacaab03ef25738bd1c77856ad8966bd57b" +dependencies = [ + "bstr", + "gix-discover", + "gix-fs", + "gix-ignore", + "gix-index", + "gix-object", + "gix-path", + "gix-pathspec", + "gix-trace", + "gix-utils", + "gix-worktree", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-discover" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c2414bdf04064e0f5a5aa029dfda1e663cf9a6c4bfc8759f2d369299bb65d8" +dependencies = [ + "bstr", + "dunce", + "gix-fs", + "gix-hash", + "gix-path", + "gix-ref", + "gix-sec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-features" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bfdd4838a8d42bd482c9f0cb526411d003ee94cc7c7b08afe5007329c71d554" +dependencies = [ + "bytes", + "crc32fast", + "crossbeam-channel", + "flate2", + "gix-hash", + "gix-trace", + "gix-utils", + "libc", + "once_cell", + "parking_lot", + "prodash", + "sha1_smol", + "thiserror 2.0.11", + "walkdir", +] + +[[package]] +name = "gix-filter" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdcc36cd7dbc63ed0ec3558645886553d1afd3cd09daa5efb9cba9cceb942bbb" +dependencies = [ + "bstr", + "encoding_rs", + "gix-attributes", + "gix-command", + "gix-hash", + "gix-object", + "gix-packetline-blocking", + "gix-path", + "gix-quote", + "gix-trace", + "gix-utils", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-fs" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "182e7fa7bfdf44ffb7cfe7451b373cdf1e00870ac9a488a49587a110c562063d" +dependencies = [ + "fastrand", + "gix-features", + "gix-utils", +] + +[[package]] +name = "gix-glob" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9c7249fa0a78f9b363aa58323db71e0a6161fd69860ed6f48dedf0ef3a314e" +dependencies = [ + "bitflags", + "bstr", + "gix-features", + "gix-path", +] + +[[package]] +name = "gix-hash" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e81c5ec48649b1821b3ed066a44efb95f1a268b35c1d91295e61252539fbe9f8" +dependencies = [ + "faster-hex", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-hashtable" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189130bc372accd02e0520dc5ab1cef318dcc2bc829b76ab8d84bbe90ac212d1" +dependencies = [ + "gix-hash", + "hashbrown 0.14.5", + "parking_lot", +] + +[[package]] +name = "gix-ignore" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f529dcb80bf9855c0a7c49f0ac588df6d6952d63a63fefc254b9c869d2cdf6f" +dependencies = [ + "bstr", + "gix-glob", + "gix-path", + "gix-trace", + "unicode-bom", +] + +[[package]] +name = "gix-index" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acd12e3626879369310fffe2ac61acc828613ef656b50c4ea984dd59d7dc85d8" +dependencies = [ + "bitflags", + "bstr", + "filetime", + "fnv", + "gix-bitmap", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-traverse", + "gix-utils", + "gix-validate", + "hashbrown 0.14.5", + "itoa", + "libc", + "memmap2", + "rustix", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-lock" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9739815270ff6940968441824d162df9433db19211ca9ba8c3fc1b50b849c642" +dependencies = [ + "gix-tempfile", + "gix-utils", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-negotiate" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a8af1ef7bbe303d30b55312b7f4d33e955de43a3642ae9b7347c623d80ef80" +dependencies = [ + "bitflags", + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-object" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc4b3a0044244f0fe22347fb7a79cca165e37829d668b41b85ff46a43e5fd68" +dependencies = [ + "bstr", + "gix-actor", + "gix-date", + "gix-features", + "gix-hash", + "gix-hashtable", + "gix-path", + "gix-utils", + "gix-validate", + "itoa", + "smallvec", + "thiserror 2.0.11", + "winnow 0.6.26", +] + +[[package]] +name = "gix-odb" +version = "0.67.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e93457df69cd09573608ce9fa4f443fbd84bc8d15d8d83adecd471058459c1b" +dependencies = [ + "arc-swap", + "gix-date", + "gix-features", + "gix-fs", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-pack", + "gix-path", + "gix-quote", + "parking_lot", + "tempfile", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-pack" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc13a475b3db735617017fb35f816079bf503765312d4b1913b18cf96f3fa515" +dependencies = [ + "clru", + "gix-chunk", + "gix-features", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-path", + "gix-tempfile", + "memmap2", + "parking_lot", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-packetline" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e5ae6bc3ac160a6bf44a55f5537813ca3ddb08549c0fd3e7ef699c73c439cd" +dependencies = [ + "bstr", + "faster-hex", + "gix-trace", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-packetline-blocking" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cbf8767c6abd5a6779f586702b5bcd8702380f4208219449cf1c9d0cd1e17c" +dependencies = [ + "bstr", + "faster-hex", + "gix-trace", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-path" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c40f12bb65a8299be0cfb90fe718e3be236b7a94b434877012980863a883a99f" +dependencies = [ + "bstr", + "gix-trace", + "home", + "once_cell", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-pathspec" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6430d3a686c08e9d59019806faa78c17315fe22ae73151a452195857ca02f86c" +dependencies = [ + "bitflags", + "bstr", + "gix-attributes", + "gix-config-value", + "gix-glob", + "gix-path", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-prompt" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79f2185958e1512b989a007509df8d61dca014aa759a22bee80cfa6c594c3b6d" +dependencies = [ + "gix-command", + "gix-config-value", + "parking_lot", + "rustix", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-protocol" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c61bd61afc6b67d213241e2100394c164be421e3f7228d3521b04f48ca5ba90" +dependencies = [ + "bstr", + "gix-credentials", + "gix-date", + "gix-features", + "gix-hash", + "gix-lock", + "gix-negotiate", + "gix-object", + "gix-ref", + "gix-refspec", + "gix-revwalk", + "gix-shallow", + "gix-trace", + "gix-transport", + "gix-utils", + "maybe-async", + "thiserror 2.0.11", + "winnow 0.6.26", +] + +[[package]] +name = "gix-quote" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49357fccdb0c85c0d3a3292a9f6db32d9b3535959b5471bb9624908f4a066c6" +dependencies = [ + "bstr", + "gix-utils", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-ref" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47adf4c5f933429f8554e95d0d92eee583cfe4b95d2bf665cd6fd4a1531ee20c" +dependencies = [ + "gix-actor", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-path", + "gix-tempfile", + "gix-utils", + "gix-validate", + "memmap2", + "thiserror 2.0.11", + "winnow 0.6.26", +] + +[[package]] +name = "gix-refspec" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59650228d8f612f68e7f7a25f517fcf386c5d0d39826085492e94766858b0a90" +dependencies = [ + "bstr", + "gix-hash", + "gix-revision", + "gix-validate", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-revision" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fe28bbccca55da6d66e6c6efc6bb4003c29d407afd8178380293729733e6b53" +dependencies = [ + "bitflags", + "bstr", + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "gix-trace", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-revwalk" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ecb80c235b1e9ef2b99b23a81ea50dd569a88a9eb767179793269e0e616247" +dependencies = [ + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-sec" +version = "0.10.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84dae13271f4313f8d60a166bf27e54c968c7c33e2ffd31c48cafe5da649875" +dependencies = [ + "bitflags", + "gix-path", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "gix-shallow" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab72543011e303e52733c85bef784603ef39632ddf47f69723def52825e35066" +dependencies = [ + "bstr", + "gix-hash", + "gix-lock", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-submodule" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74972fe8d46ac8a09490ae1e843b4caf221c5b157c5ac17057e8e1c38417a3ac" +dependencies = [ + "bstr", + "gix-config", + "gix-path", + "gix-pathspec", + "gix-refspec", + "gix-url", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-tempfile" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2558f423945ef24a8328c55d1fd6db06b8376b0e7013b1bb476cc4ffdf678501" +dependencies = [ + "gix-fs", + "libc", + "once_cell", + "parking_lot", + "tempfile", +] + +[[package]] +name = "gix-trace" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c396a2036920c69695f760a65e7f2677267ccf483f25046977d87e4cb2665f7" + +[[package]] +name = "gix-transport" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11187418489477b1b5b862ae1aedbbac77e582f2c4b0ef54280f20cfe5b964d9" +dependencies = [ + "base64", + "bstr", + "curl", + "gix-command", + "gix-credentials", + "gix-features", + "gix-packetline", + "gix-quote", + "gix-sec", + "gix-url", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-traverse" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bec70e53896586ef32a3efa7e4427b67308531ed186bb6120fb3eca0f0d61b4" +dependencies = [ + "bitflags", + "gix-commitgraph", + "gix-date", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-url" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29218c768b53dd8f116045d87fec05b294c731a4b2bdd257eeca2084cc150b13" +dependencies = [ + "bstr", + "gix-features", + "gix-path", + "percent-encoding", + "thiserror 2.0.11", + "url", +] + +[[package]] +name = "gix-utils" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff08f24e03ac8916c478c8419d7d3c33393da9bb41fa4c24455d5406aeefd35f" +dependencies = [ + "bstr", + "fastrand", + "unicode-normalization", +] + +[[package]] +name = "gix-validate" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eaa01c3337d885617c0a42e92823922a2aea71f4caeace6fe87002bdcadbd90" +dependencies = [ + "bstr", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-worktree" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6673512f7eaa57a6876adceca6978a501d6c6569a4f177767dc405f8b9778958" +dependencies = [ + "bstr", + "gix-attributes", + "gix-features", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-ignore", + "gix-index", + "gix-object", + "gix-path", + "gix-validate", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "globset" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "html-escape" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", +] + +[[package]] +name = "http-auth" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "150fa4a9462ef926824cf4519c84ed652ca8f4fbae34cb8af045b5cbcaf98822" +dependencies = [ + "memchr", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "ignore" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata 0.4.9", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "im-rc" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "is_executable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a1b5bad6f9072935961dfbf1cced2f3d129963d091b6f69f007fe04e758ae2" +dependencies = [ + "winapi", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jiff" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c04ef77ae73f3cf50510712722f0c4e8b46f5aaa1bf5ffad2ae213e6495e78e5" +dependencies = [ + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", + "windows-sys 0.59.0", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2cec2f5d266af45a071ece48b1fb89f3b00b2421ac3a5fe10285a6caaa60d3" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a63c62e404e7b92979d2792352d885a7f8f83fd1d0d31eea582d77b2ceca697e" +dependencies = [ + "jiff-tzdb", +] + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "kstring" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "libgit2-sys" +version = "0.18.0+1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a117465e7e1597e8febea8bb0c410f1c7fb93b1e1cddf34363f8390367ffec" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + +[[package]] +name = "libnghttp2-sys" +version = "0.1.11+1.64.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b6c24e48a7167cffa7119da39d577fa482e66c688a4aac016bee862e1a713c4" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", + "redox_syscall", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8935b44e7c13394a179a438e0cebba0fe08fe01b54f152e29a93b5cf993fd4" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libssh2-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220e4f05ad4a218192533b300327f5150e809b54c4ec83b5a1d91833601811b9" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "libz-sys" +version = "1.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "maybe-async" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +dependencies = [ + "adler2", +] + +[[package]] +name = "miow" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "normpath" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + +[[package]] +name = "opener" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0812e5e4df08da354c851a3376fead46db31c2214f849d3de356d774d057681" +dependencies = [ + "bstr", + "dbus", + "normpath", + "windows-sys 0.59.0", +] + +[[package]] +name = "openssl" +version = "0.10.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-src" +version = "111.28.2+1.1.1w" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1830e20a48a975ca898ca8c1d036a36c3c6c5cb7dabc1c216706587857920f" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db7e971c2c2bba161b2d2fdf37080177eff520b3bc044787c7f1f5f9e78d869b" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "orion" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd806049e71da4c4a7880466b37afdc5a4c5b35a398b0d4fd9ff5d278d3b4db9" +dependencies = [ + "fiat-crypto", + "subtle", + "zeroize", +] + +[[package]] +name = "os_info" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a604e53c24761286860eba4e2c8b23a0161526476b1de520139d69cdb85a6b5" +dependencies = [ + "log", + "windows-sys 0.52.0", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pasetors" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54944fa25a6e7c9c5b3315f118d360cc00d555cf53bb2b2fdf32dd31c71b729" +dependencies = [ + "ct-codecs", + "ed25519-compact", + "getrandom 0.3.1", + "orion", + "p384", + "rand_core 0.6.4", + "regex", + "serde", + "serde_json", + "sha2", + "subtle", + "time", + "zeroize", +] + +[[package]] +name = "pathdiff" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prodash" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a266d8d6020c61a437be704c5e618037588e1985c7dbb7bf8d265db84cffe325" +dependencies = [ + "log", + "parking_lot", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha", + "rand_core 0.9.0", + "zerocopy 0.8.17", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.0", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +dependencies = [ + "getrandom 0.3.1", + "zerocopy 0.8.17", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rusqlite" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6d5e5acb6f6129fe3f7ba0a7fc77bca1942cb568535e18e7bc40262baf3110" +dependencies = [ + "bitflags", + "fallible-iterator", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc-stable-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2febf9acc5ee5e99d1ad0afcdbccc02d87aa3f857a1f01f825b80eacf8edfcd1" + +[[package]] +name = "rustfix" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f66156d7471ff4f12253cd7fd76dfe637a595a9418168154e8570f3947fe9a8" +dependencies = [ + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" +dependencies = [ + "serde", +] + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-untagged" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2676ba99bd82f75cae5cbd2c8eda6fa0b8760f18978ea840e980dd5567b5c5b6" +dependencies = [ + "erased-serde", + "serde", + "typeid", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_ignored" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e319a36d1b52126a0d608f24e93b2d81297091818cd70625fcf50a15d84ddf" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shell-escape" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "snapbox" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96dcfc4581e3355d70ac2ee14cfdf81dce3d85c85f1ed9e2c1d3013f53b3436b" +dependencies = [ + "anstream", + "anstyle", + "anstyle-svg", + "content_inspector", + "dunce", + "filetime", + "normalize-line-endings", + "regex", + "serde", + "serde_json", + "similar", + "snapbox-macros", + "tempfile", + "walkdir", +] + +[[package]] +name = "snapbox-macros" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16569f53ca23a41bb6f62e0a5084aa1661f4814a67fa33696a79073e03a664af" +dependencies = [ + "anstream", +] + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "supports-hyperlinks" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f44ed3c63152de6a9f90acbea1a110441de43006ea51bcce8f436196a288b" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tar" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" +dependencies = [ + "filetime", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom 0.3.1", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "terminal_size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" +dependencies = [ + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.7.1", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-chrome" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf0a738ed5d6450a9fb96e86a23ad808de2b727fd1394585da5cdd6788ffe724" +dependencies = [ + "serde_json", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "typeid" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-bom" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" +dependencies = [ + "zerocopy-derive 0.8.17", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +]

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 literal 0 HcmV?d00001 diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/tikv.tgz b/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/tikv.tgz new file mode 100644 index 0000000000000000000000000000000000000000..74add19b38a42fcd47ac1651aa454f510d1a97e4 GIT binary patch literal 44476 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 literal 0 HcmV?d00001 diff --git a/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/toml-rs.tgz b/collector/compile-benchmarks/cargo-0.87.1/benches/workspaces/toml-rs.tgz new file mode 100644 index 0000000000000000000000000000000000000000..9acab198240ab52e22f0b4a1994243044c3c3215 GIT binary patch literal 1782 zcmVWqI)z zZT~IGvRc$b^=X;A_|PvM#iz>fsErPaMDLtS(raZCvBEeBMk@kNDl0>(F2`|Y)xo+Q zAP-#*!>0dqHp6+BTR#o$dgfN}A#`1O@t=Y(9eq=x(MZGWksiCYIRi< zj|8SQ_CBoLW?r7+uLgAs?LU99Kk1y`V?grjWj?8`)p{sA;L2&mn=bOE;3EZ&l z@|Xz8ZC3++`+i<*@D+47aMj|NF2AepHLB(~Y~#YUTfn?<+hN&u{V4GUsi*w%j(f_# zXD0e$pN=v=eU8I}8(`6PsOdN?v`wlP)n!?s`faS6vA=O0YA~tSn-#2~8C>3lzRG&` zIN`V{*^W15gP+jMZ_&ZZaRyY_HL;Aa>$jrh0{IXPJKJz^(gf z`LC|Msd4J}&65@L@L>rkiSn+C<#)KNZdLyXv#;_V?fM9ftB1bCHO9rt=mu8~?fWLV zP_Js73{atad9-o2{ND4ZKkBm$BOufFO;yA;Y#&s~*4`67e(0yjCYeX70%CnHzz8)} zv253{L45XyyqF`d;r0iFdk4w`6!T(L2Wa|nuD9R3o4rBomoQ=3e;T(Q-|y7Gt&F?p zZ@+%?)!VP9>zH3|+P)sz?)IaU+4FKTl~a>_6}7wWadmXNHLN|{x!nN$FzL57ro?&i zhv)yk3$s=25xiID|J)AwpQtnczasuWd+X_s0x#h&G(R~1Q>oARzfS&tnx#EKiEAcs??V8DAQ-7xkik$bEd$GpOcM7z z889jtA5mJtGZs9Q{*N6hFW%T%lJ;L7Bt?UU;R9;7apEXh49NH&$rtIRgSw zaRGumOG8SEIYeOpRFe-Z#n0YR1zprPDbku^NLaHrFW<}5&~rcBS%vj8IMQ7+BS8*wV8aV zlPHTsMc_IlX{k`jBVRb=3k)ZlYyy$A(JUiJkfODd7(r1fA4#y39|dQ>0(%~vM^eAP zrBVBU`|mup3hfl&fCv&T#u4|u;Nv zOwZNmf#K@Z97z)9SPUf*{uUgZ=$H2&PBQ^NY(qx*j;Z4mhI0{R#176u2|- zSxxqL>9H2<>(); + files.sort(); + for path in files { + if path.extension() != Some(extension) { + continue; + } + println!("cargo:rerun-if-changed={}", path.display()); + ar.append_path_with_name(&path, path.file_name().unwrap()) + .unwrap(); + } + }; + + add_files(Path::new("src/etc/man"), OsStr::new("1")); + add_files(Path::new("src/doc/man/generated_txt"), OsStr::new("txt")); + let encoder = ar.into_inner().unwrap(); + encoder.finish().unwrap(); +} + +struct CommitInfo { + hash: String, + short_hash: String, + date: String, +} + +fn commit_info_from_git() -> Option { + if !Path::new(".git").exists() { + return None; + } + + let output = match Command::new("git") + .arg("log") + .arg("-1") + .arg("--date=short") + .arg("--format=%H %h %cd") + .arg("--abbrev=9") + .output() + { + Ok(output) if output.status.success() => output, + _ => return None, + }; + + let stdout = String::from_utf8(output.stdout).unwrap(); + let mut parts = stdout.split_whitespace().map(|s| s.to_string()); + + Some(CommitInfo { + hash: parts.next()?, + short_hash: parts.next()?, + date: parts.next()?, + }) +} + +// The rustc source tarball is meant to contain all the source code to build an exact copy of the +// toolchain, but it doesn't include the git repository itself. It wouldn't thus be possible to +// populate the version information with the commit hash and the commit date. +// +// To work around this, the rustc build process obtains the git information when creating the +// source tarball and writes it to the `git-commit-info` file. The build process actually creates +// at least *two* of those files, one for Rust as a whole (in the root of the tarball) and one +// specifically for Cargo (in src/tools/cargo). This function loads that file. +// +// The file is a newline-separated list of full commit hash, short commit hash, and commit date. +fn commit_info_from_rustc_source_tarball() -> Option { + let path = Path::new("git-commit-info"); + if !path.exists() { + return None; + } + + // Dependency tracking is a nice to have for this (git doesn't do it), so if the path is not + // valid UTF-8 just avoid doing it rather than erroring out. + if let Some(utf8) = path.to_str() { + println!("cargo:rerun-if-changed={utf8}"); + } + + let content = std::fs::read_to_string(&path).ok()?; + let mut parts = content.split('\n').map(|s| s.to_string()); + Some(CommitInfo { + hash: parts.next()?, + short_hash: parts.next()?, + date: parts.next()?, + }) +} + +fn commit_info() { + // Var set by bootstrap whenever omit-git-hash is enabled in rust-lang/rust's config.toml. + println!("cargo:rerun-if-env-changed=CFG_OMIT_GIT_HASH"); + // ALLOWED: Accessing environment during build time shouldn't be prohibited. + #[allow(clippy::disallowed_methods)] + if std::env::var_os("CFG_OMIT_GIT_HASH").is_some() { + return; + } + + let Some(git) = commit_info_from_git().or_else(commit_info_from_rustc_source_tarball) else { + return; + }; + + println!("cargo:rustc-env=CARGO_COMMIT_HASH={}", git.hash); + println!("cargo:rustc-env=CARGO_COMMIT_SHORT_HASH={}", git.short_hash); + println!("cargo:rustc-env=CARGO_COMMIT_DATE={}", git.date); +} + +#[allow(clippy::disallowed_methods)] +fn windows_manifest() { + use std::env; + let target_os = env::var("CARGO_CFG_TARGET_OS"); + let target_env = env::var("CARGO_CFG_TARGET_ENV"); + if Ok("windows") == target_os.as_deref() && Ok("msvc") == target_env.as_deref() { + static WINDOWS_MANIFEST_FILE: &str = "windows.manifest.xml"; + + let mut manifest = env::current_dir().unwrap(); + manifest.push(WINDOWS_MANIFEST_FILE); + + println!("cargo:rerun-if-changed={WINDOWS_MANIFEST_FILE}"); + // Embed the Windows application manifest file. + println!("cargo:rustc-link-arg-bin=cargo=/MANIFEST:EMBED"); + println!( + "cargo:rustc-link-arg-bin=cargo=/MANIFESTINPUT:{}", + manifest.to_str().unwrap() + ); + // Turn linker warnings into errors. + println!("cargo:rustc-link-arg-bin=cargo=/WX"); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/ci/clean-test-output.sh b/collector/compile-benchmarks/cargo-0.87.1/ci/clean-test-output.sh new file mode 100755 index 000000000..f1f2ec61c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/ci/clean-test-output.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# This script remove test and benchmark output and displays disk usage. + +set -euo pipefail + +df -h +rm -rf target/tmp +df -h diff --git a/collector/compile-benchmarks/cargo-0.87.1/ci/dump-environment.sh b/collector/compile-benchmarks/cargo-0.87.1/ci/dump-environment.sh new file mode 100755 index 000000000..b9b7ec56c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/ci/dump-environment.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# This script dumps information about the build environment to stdout. + +set -euo pipefail +IFS=$'\n\t' + +echo "environment variables:" +printenv | sort +echo + +echo "disk usage:" +df -h +echo + +echo "CPU info:" +if [[ "${OSTYPE}" = "darwin"* ]]; then + system_profiler SPHardwareDataType || true + sysctl hw || true +else + cat /proc/cpuinfo || true + cat /proc/meminfo || true +fi diff --git a/collector/compile-benchmarks/cargo-0.87.1/ci/fetch-smoke-test.sh b/collector/compile-benchmarks/cargo-0.87.1/ci/fetch-smoke-test.sh new file mode 100755 index 000000000..17993d1fd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/ci/fetch-smoke-test.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# This script builds with static curl, and verifies that fetching works. + +set -ex + +if [[ -z "$RUNNER_TEMP" ]] +then + echo "RUNNER_TEMP must be set" + exit 1 +fi + +if [ ! -f Cargo.toml ]; then + echo "Must be run from root of project." + exit 1 +fi + + +# Building openssl on Windows is a pain. +if [[ $(rustc -Vv | grep host:) != *windows* ]]; then + FEATURES='vendored-openssl,curl-sys/static-curl,curl-sys/force-system-lib-on-osx' + export LIBZ_SYS_STATIC=1 +fi + +cargo build --features "$FEATURES" +export CARGO_HOME=$RUNNER_TEMP/chome +target/debug/cargo fetch +rm -rf $CARGO_HOME diff --git a/collector/compile-benchmarks/cargo-0.87.1/ci/generate.py b/collector/compile-benchmarks/cargo-0.87.1/ci/generate.py new file mode 100644 index 000000000..b750729dc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/ci/generate.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +MAPPING = { + "build-script.html": "https://doc.rust-lang.org/cargo/reference/build-scripts.html", + "config.html": None, + "crates-io.html": "https://doc.rust-lang.org/cargo/reference/publishing.html", + "environment-variables.html": None, + "external-tools.html": None, + "faq.html": "https://doc.rust-lang.org/cargo/faq.html", + "guide.html": "https://doc.rust-lang.org/cargo/guide/", + "index.html": "https://doc.rust-lang.org/cargo/", + "manifest.html": None, + "pkgid-spec.html": None, + "policies.html": "https://crates.io/policies", + "source-replacement.html": None, + "specifying-dependencies.html": None, +} + +TEMPLATE = """\ + + + + +Page Moved + + +This page has moved. Click here to go to the new page. + + +""" + +def main(): + for name in sorted(MAPPING): + with open(name, 'w') as f: + mapped = MAPPING[name] + if mapped is None: + mapped = "https://doc.rust-lang.org/cargo/reference/{}".format(name) + f.write(TEMPLATE.format(name=name, mapped=mapped)) + + # WARN: The CNAME file is for GitHub to redirect requests to the custom domain. + # Missing this may entail security hazard and domain takeover. + # See + with open('CNAME', 'w') as f: + f.write('doc.crates.io') + +if __name__ == '__main__': + main() diff --git a/collector/compile-benchmarks/cargo-0.87.1/ci/validate-man.sh b/collector/compile-benchmarks/cargo-0.87.1/ci/validate-man.sh new file mode 100755 index 000000000..a3f114214 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/ci/validate-man.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# This script validates that there aren't any changes to the man pages. + +set -e + +cargo_man="src/doc" +mdman_man="crates/mdman/doc" + +changes=$(git status --porcelain -- $cargo_man $mdman_man) +if [ -n "$changes" ] +then + echo "git directory must be clean before running this script." + exit 1 +fi + +cargo build-man + +changes=$(git status --porcelain -- $cargo_man $mdman_man) +if [ -n "$changes" ] +then + echo "Detected changes of man pages:" + echo "$changes" + echo + echo 'Please run `cargo build-man` to rebuild the man pages' + echo "and commit the changes." + exit 1 +fi diff --git a/collector/compile-benchmarks/cargo-0.87.1/ci/validate-version-bump.sh b/collector/compile-benchmarks/cargo-0.87.1/ci/validate-version-bump.sh new file mode 100755 index 000000000..94896711f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/ci/validate-version-bump.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# This script checks if a crate needs a version bump. +# +# At the time of writing, it doesn't check what kind of bump is required. +# In the future, we could take SemVer compatibliity into account, like +# integrating `cargo-semver-checks` of else +# +# Inputs: +# BASE_SHA The commit SHA of the branch where the PR wants to merge into. +# HEAD_SHA The commit SHA that triggered the workflow. + +set -euo pipefail + +# When `BASE_SHA` is missing, we assume it is from GitHub merge queue merge commit, +# so hope `HEAD~` to find the previous commit on master branch. +base_sha=$(git rev-parse "${BASE_SHA:-HEAD~1}") +head_sha=$(git rev-parse "${HEAD_SHA:-HEAD}") + +echo "Base revision is $base_sha" +echo "Head revision is $head_sha" + +cargo bump-check --base-rev "$base_sha" --head-rev "$head_sha" diff --git a/collector/compile-benchmarks/cargo-0.87.1/clippy.toml b/collector/compile-benchmarks/cargo-0.87.1/clippy.toml new file mode 100644 index 000000000..dff120e95 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/clippy.toml @@ -0,0 +1,11 @@ +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" }, +] +disallowed-types = [ + { path = "std::sync::atomic::AtomicU64", reason = "not portable. See rust-lang/cargo#12988" }, +] diff --git a/collector/compile-benchmarks/cargo-0.87.1/credential/README.md b/collector/compile-benchmarks/cargo-0.87.1/credential/README.md new file mode 100644 index 000000000..168cc71c3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/credential/README.md @@ -0,0 +1,8 @@ +# Cargo Credential Packages + +This directory contains Cargo packages for handling storage of tokens in a +secure manner. + +`cargo-credential` is a generic library to assist writing a credential +process. The other directories contain implementations that integrate with +specific credential systems. diff --git a/collector/compile-benchmarks/cargo-0.87.1/deny.toml b/collector/compile-benchmarks/cargo-0.87.1/deny.toml new file mode 100644 index 000000000..97963aa09 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/deny.toml @@ -0,0 +1,243 @@ +# This template contains all of the possible sections and their default values + +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# The values provided in this template are the default values that will be used +# when any section or field is not specified in your own configuration + +# Root options + +# The graph table configures how the dependency graph is constructed and thus +# which crates the checks are performed against +[graph] +# If 1 or more target triples (and optionally, target_features) are specified, +# only the specified targets will be checked when running `cargo deny check`. +# This means, if a particular package is only ever used as a target specific +# dependency, such as, for example, the `nix` crate only being used via the +# `target_family = "unix"` configuration, that only having windows targets in +# this list would mean the nix crate, as well as any of its exclusive +# dependencies not shared by any other crates, would be ignored, as the target +# list here is effectively saying which targets you are building for. +targets = [ + # The triple can be any string, but only the target triples built in to + # rustc (as of 1.40) can be checked against actual config expressions + #"x86_64-unknown-linux-musl", + # You can also specify which target_features you promise are enabled for a + # particular target. target_features are currently not validated against + # the actual valid features supported by the target architecture. + #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, +] +# When creating the dependency graph used as the source of truth when checks are +# executed, this field can be used to prune crates from the graph, removing them +# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate +# is pruned from the graph, all of its dependencies will also be pruned unless +# they are connected to another crate in the graph that hasn't been pruned, +# so it should be used with care. The identifiers are [Package ID Specifications] +# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html) +#exclude = [] +# If true, metadata will be collected with `--all-features`. Note that this can't +# be toggled off if true, if you want to conditionally enable `--all-features` it +# is recommended to pass `--all-features` on the cmd line instead +all-features = false +# If true, metadata will be collected with `--no-default-features`. The same +# caveat with `all-features` applies +no-default-features = false +# If set, these feature will be enabled when collecting metadata. If `--features` +# is specified on the cmd line they will take precedence over this option. +#features = [] + +# The output table provides options for how/if diagnostics are outputted +[output] +# When outputting inclusion graphs in diagnostics that include features, this +# option can be used to specify the depth at which feature edges will be added. +# This option is included since the graphs can be quite large and the addition +# of features from the crate(s) to all of the graph roots can be far too verbose. +# This option can be overridden via `--feature-depth` on the cmd line +feature-depth = 1 + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The path where the advisory databases are cloned/fetched into +#db-path = "$CARGO_HOME/advisory-dbs" +# The url(s) of the advisory databases to use +#db-urls = ["https://github.com/rustsec/advisory-db"] +yanked = "warn" +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +ignore = [ + #"RUSTSEC-0000-0000", + #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, + #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish + #{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" }, +] +# If this is true, then cargo deny will use the git executable to fetch advisory database. +# If this is false, then it uses a built-in git library. +# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. +# See Git Authentication for more information about setting up git authentication. +#git-fetch-with-cli = true + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "MIT-0", + "Apache-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "MPL-2.0", + "Unicode-3.0", + "CC0-1.0", + "ISC", + "Zlib", +] +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], crate = "adler32" }, +] + +# Some crates don't have (easily) machine readable licensing information, +# adding a clarification entry for it allows you to manually specify the +# licensing information +#[[licenses.clarify]] +# The package spec the clarification applies to +#crate = "ring" +# The SPDX expression for the license requirements of the crate +#expression = "MIT AND ISC AND OpenSSL" +# One or more files in the crate's source used as the "source of truth" for +# the license expression. If the contents match, the clarification will be used +# when running the license check, otherwise the clarification will be ignored +# and the crate will be checked normally, which may produce warnings or errors +# depending on the rest of your configuration +#license-files = [ +# Each entry is a crate relative path, and the (opaque) hash of its contents +#{ path = "LICENSE", hash = 0xbd0eed23 } +#] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = false +# One or more private registries that you might publish crates to, if a crate +# is only published to private registries, and ignore is true, the crate will +# not have its license(s) checked +registries = [ + #"https://sekretz.com/registry +] + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when a crate version requirement is `*` +wildcards = "allow" +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * 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 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 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! +allow = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" }, +] +# List of crates to deny +deny = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" }, + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] }, +] + +# List of features to allow/deny +# Each entry the name of a crate and a version range. If version is +# not specified, all versions will be matched. +#[[bans.features]] +#crate = "reqwest" +# Features to not allow +#deny = ["json"] +# Features to allow +#allow = [ +# "rustls", +# "__rustls", +# "__tls", +# "hyper-rustls", +# "rustls", +# "rustls-pemfile", +# "rustls-tls-webpki-roots", +# "tokio-rustls", +# "webpki-roots", +#] +# If true, the allowed features must exactly match the enabled feature set. If +# this is set there is no point setting `deny` +#exact = true + +# Certain crates/versions that will be skipped when doing duplicate detection. +skip = [ + #"ansi_term@0.11.0", + #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" }, +] +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive +# dependencies starting at the specified crate, up to a certain depth, which is +# by default infinite. +skip-tree = [ + #"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies + #{ crate = "ansi_term@0.11.0", depth = 20 }, +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "warn" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "warn" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [] + +[sources.allow-org] +# github.com organizations to allow git sources for +github = [] +# gitlab.com organizations to allow git sources for +gitlab = [] +# bitbucket.org organizations to allow git sources for +bitbucket = [] diff --git a/collector/compile-benchmarks/cargo-0.87.1/perf-config.json b/collector/compile-benchmarks/cargo-0.87.1/perf-config.json new file mode 100644 index 000000000..338014ddc --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/perf-config.json @@ -0,0 +1,7 @@ +{ + "cargo_opts": "--lib", + "runs": 1, + "touch_file": "src/cargo/lib.rs", + "category": "primary", + "artifact": "library" +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/publish.py b/collector/compile-benchmarks/cargo-0.87.1/publish.py new file mode 100755 index 000000000..f01cbc666 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/publish.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 + +# This script is used to publish Cargo to crates.io. +# +# This is run automatically every 6 weeks by the Release team's automation +# whose source is at https://github.com/rust-lang/simpleinfra/. +# +# See https://doc.crates.io/contrib/process/release.html for more about +# Cargo's release process. + +import os +import re +import subprocess +import urllib.request +from urllib.error import HTTPError + + +# Whenever you add a new crate to this list that does NOT start with "cargo-" +# you must reach out to the infra team to add the crate to the list of crates +# allowed to be published from the "cargo CI" crates.io token. +TO_PUBLISH = [ + 'credential/cargo-credential', + 'credential/cargo-credential-libsecret', + 'credential/cargo-credential-wincred', + 'credential/cargo-credential-1password', + 'credential/cargo-credential-macos-keychain', + 'crates/rustfix', + 'crates/cargo-platform', + 'crates/cargo-util', + 'crates/crates-io', + 'crates/cargo-util-schemas', + 'crates/cargo-test-macro', + 'crates/cargo-test-support', + '.', +] + + +def already_published(name, version): + url = f'https://static.crates.io/crates/{name}/{version}/download' + try: + urllib.request.urlopen(url) + except HTTPError as e: + # 403 and 404 are common responses to assume it is not published + if 400 <= e.code < 500: + return False + print(f'error: failed to check if {name} {version} is already published') + print(f' HTTP response error code {e.code} checking {url}') + raise + return True + + +def maybe_publish(path): + content = open(os.path.join(path, 'Cargo.toml')).read() + name = re.search('^name = "([^"]+)"', content, re.M).group(1) + version = re.search('^version = "([^"]+)"', content, re.M).group(1) + if already_published(name, version): + print('%s %s is already published, skipping' % (name, version)) + return False + subprocess.check_call(['cargo', 'publish', '--no-verify'], cwd=path) + return True + + +def main(): + print('Starting publish...') + for path in TO_PUBLISH: + maybe_publish(path) + + print('Publish complete!') + + +if __name__ == '__main__': + main() diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/cli.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/cli.rs new file mode 100644 index 000000000..aa72d7c1a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/cli.rs @@ -0,0 +1,712 @@ +use anyhow::{anyhow, Context as _}; +use cargo::core::{features, CliUnstable}; +use cargo::util::context::TermConfig; +use cargo::{drop_print, drop_println, CargoResult}; +use clap::builder::UnknownArgumentValueParser; +use itertools::Itertools; +use std::collections::HashMap; +use std::ffi::OsStr; +use std::ffi::OsString; +use std::fmt::Write; + +use super::commands; +use super::list_commands; +use crate::command_prelude::*; +use crate::util::is_rustup; +use cargo::core::shell::ColorChoice; +use cargo::util::style; + +#[tracing::instrument(skip_all)] +pub fn main(gctx: &mut GlobalContext) -> CliResult { + // CAUTION: Be careful with using `config` until it is configured below. + // In general, try to avoid loading config values unless necessary (like + // the [alias] table). + + let args = cli(gctx).try_get_matches()?; + + // Update the process-level notion of cwd + if let Some(new_cwd) = args.get_one::("directory") { + // This is a temporary hack. + // This cannot access `GlobalContext`, so this is a bit messy. + // This does not properly parse `-Z` flags that appear after the subcommand. + // The error message is not as helpful as the standard one. + let nightly_features_allowed = matches!(&*features::channel(), "nightly" | "dev"); + if !nightly_features_allowed + || (nightly_features_allowed + && !args + .get_many("unstable-features") + .map(|mut z| z.any(|value: &String| value == "unstable-options")) + .unwrap_or(false)) + { + return Err(anyhow::format_err!( + "the `-C` flag is unstable, \ + pass `-Z unstable-options` on the nightly channel to enable it" + ) + .into()); + } + std::env::set_current_dir(&new_cwd).context("could not change to requested directory")?; + gctx.reload_cwd()?; + } + + let (expanded_args, global_args) = expand_aliases(gctx, args, vec![])?; + + let is_verbose = expanded_args.verbose() > 0; + + if expanded_args + .get_one::("unstable-features") + .map(String::as_str) + == Some("help") + { + // Don't let config errors get in the way of parsing arguments + let _ = configure_gctx(gctx, &expanded_args, None, global_args, None); + print_zhelp(gctx); + } else if expanded_args.flag("version") { + // Don't let config errors get in the way of parsing arguments + let _ = configure_gctx(gctx, &expanded_args, None, global_args, None); + let version = get_version_string(is_verbose); + drop_print!(gctx, "{}", version); + } else if let Some(code) = expanded_args.get_one::("explain") { + // Don't let config errors get in the way of parsing arguments + let _ = configure_gctx(gctx, &expanded_args, None, global_args, None); + let mut procss = gctx.load_global_rustc(None)?.process(); + procss.arg("--explain").arg(code).exec()?; + } else if expanded_args.flag("list") { + // Don't let config errors get in the way of parsing arguments + let _ = configure_gctx(gctx, &expanded_args, None, global_args, None); + print_list(gctx, is_verbose); + } else { + let (cmd, subcommand_args) = match expanded_args.subcommand() { + Some((cmd, args)) => (cmd, args), + _ => { + // No subcommand provided. + cli(gctx).print_help()?; + return Ok(()); + } + }; + let exec = Exec::infer(cmd)?; + configure_gctx( + gctx, + &expanded_args, + Some(subcommand_args), + global_args, + Some(&exec), + )?; + super::init_git(gctx); + + exec.exec(gctx, subcommand_args)?; + } + Ok(()) +} + +fn print_zhelp(gctx: &GlobalContext) { + let header = style::HEADER; + let literal = style::LITERAL; + let placeholder = style::PLACEHOLDER; + + let options = CliUnstable::help(); + let max_length = options + .iter() + .filter(|(_, help)| help.is_some()) + .map(|(option_name, _)| option_name.len()) + .max() + .unwrap_or(0); + let z_flags = options + .iter() + .filter(|(_, help)| help.is_some()) + .map(|(opt, help)| { + let opt = opt.replace("_", "-"); + let help = help.unwrap(); + format!(" {literal}-Z {opt:Installed Commands:") + ); + for (name, command) in list_commands(gctx) { + let known_external_desc = known_external_command_descriptions.get(name.as_str()); + let literal = style::LITERAL; + match command { + CommandInfo::BuiltIn { about } => { + assert!( + known_external_desc.is_none(), + "known_external_commands shouldn't contain builtin `{name}`", + ); + let summary = about.unwrap_or_default(); + let summary = summary.lines().next().unwrap_or(&summary); // display only the first line + drop_println!(gctx, " {literal}{name:<20}{literal:#} {summary}"); + } + CommandInfo::External { path } => { + if let Some(desc) = known_external_desc { + drop_println!(gctx, " {literal}{name:<20}{literal:#} {desc}"); + } else if is_verbose { + drop_println!( + gctx, + " {literal}{name:<20}{literal:#} {}", + path.display() + ); + } else { + drop_println!(gctx, " {literal}{name}{literal:#}"); + } + } + CommandInfo::Alias { target } => { + drop_println!( + gctx, + " {literal}{name:<20}{literal:#} alias: {}", + target.iter().join(" ") + ); + } + } + } +} + +pub fn get_version_string(is_verbose: bool) -> String { + let version = cargo::version(); + let mut version_string = format!("cargo {}\n", version); + if is_verbose { + version_string.push_str(&format!("release: {}\n", version.version)); + if let Some(ref ci) = version.commit_info { + version_string.push_str(&format!("commit-hash: {}\n", ci.commit_hash)); + version_string.push_str(&format!("commit-date: {}\n", ci.commit_date)); + } + writeln!(version_string, "host: {}", env!("RUST_HOST_TARGET")).unwrap(); + add_libgit2(&mut version_string); + add_curl(&mut version_string); + add_ssl(&mut version_string); + writeln!(version_string, "os: {}", os_info::get()).unwrap(); + } + version_string +} + +fn add_libgit2(version_string: &mut String) { + let git2_v = git2::Version::get(); + let lib_v = git2_v.libgit2_version(); + let vendored = if git2_v.vendored() { + format!("vendored") + } else { + format!("system") + }; + writeln!( + version_string, + "libgit2: {}.{}.{} (sys:{} {})", + lib_v.0, + lib_v.1, + lib_v.2, + git2_v.crate_version(), + vendored + ) + .unwrap(); +} + +fn add_curl(version_string: &mut String) { + let curl_v = curl::Version::get(); + let vendored = if curl_v.vendored() { + format!("vendored") + } else { + format!("system") + }; + writeln!( + version_string, + "libcurl: {} (sys:{} {} ssl:{})", + curl_v.version(), + curl_sys::rust_crate_version(), + vendored, + curl_v.ssl_version().unwrap_or("none") + ) + .unwrap(); +} + +fn add_ssl(version_string: &mut String) { + #[cfg(feature = "openssl")] + { + writeln!(version_string, "ssl: {}", openssl::version::version()).unwrap(); + } + #[cfg(not(feature = "openssl"))] + { + let _ = version_string; // Silence unused warning. + } +} + +/// Expands aliases recursively to collect all the command line arguments. +/// +/// [`GlobalArgs`] need to be extracted before expanding aliases because the +/// clap code for extracting a subcommand discards global options +/// (appearing before the subcommand). +#[tracing::instrument(skip_all)] +fn expand_aliases( + gctx: &mut GlobalContext, + args: ArgMatches, + mut already_expanded: Vec, +) -> Result<(ArgMatches, GlobalArgs), CliError> { + if let Some((cmd, sub_args)) = args.subcommand() { + let exec = commands::builtin_exec(cmd); + let aliased_cmd = super::aliased_command(gctx, cmd); + + match (exec, aliased_cmd) { + (Some(_), Ok(Some(_))) => { + // User alias conflicts with a built-in subcommand + gctx.shell().warn(format!( + "user-defined alias `{}` is ignored, because it is shadowed by a built-in command", + cmd, + ))?; + } + (Some(_), Ok(None) | Err(_)) => { + // Here we ignore errors from aliasing as we already favor built-in command, + // and alias doesn't involve in this context. + + if let Some(values) = sub_args.get_many::("") { + // Command is built-in and is not conflicting with alias, but contains ignored values. + return Err(anyhow::format_err!( + "\ +trailing arguments after built-in command `{}` are unsupported: `{}` + +To pass the arguments to the subcommand, remove `--`", + cmd, + values.map(|s| s.to_string_lossy()).join(" "), + ) + .into()); + } + } + (None, Ok(None)) => {} + (None, Ok(Some(alias))) => { + // Check if a user-defined alias is shadowing an external subcommand + // (binary of the form `cargo-`) + // Currently this is only a warning, but after a transition period this will become + // a hard error. + if super::builtin_aliases_execs(cmd).is_none() { + if let Some(path) = super::find_external_subcommand(gctx, cmd) { + gctx.shell().warn(format!( + "\ +user-defined alias `{}` is shadowing an external subcommand found at: `{}` +This was previously accepted but is being phased out; it will become a hard error in a future release. +For more information, see issue #10049 .", + cmd, + path.display(), + ))?; + } + } + if commands::run::is_manifest_command(cmd) { + if gctx.cli_unstable().script { + return Ok((args, GlobalArgs::default())); + } else { + gctx.shell().warn(format_args!( + "\ +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 ." + ))?; + } + } + + let mut alias = alias + .into_iter() + .map(|s| OsString::from(s)) + .collect::>(); + alias.extend( + sub_args + .get_many::("") + .unwrap_or_default() + .cloned(), + ); + // new_args strips out everything before the subcommand, so + // capture those global options now. + // Note that an alias to an external command will not receive + // these arguments. That may be confusing, but such is life. + let global_args = GlobalArgs::new(sub_args); + let new_args = cli(gctx).no_binary_name(true).try_get_matches_from(alias)?; + + let Some(new_cmd) = new_args.subcommand_name() else { + return Err(anyhow!( + "subcommand is required, add a subcommand to the command alias `alias.{cmd}`" + ) + .into()); + }; + + already_expanded.push(cmd.to_string()); + if already_expanded.contains(&new_cmd.to_string()) { + // Crash if the aliases are corecursive / unresolvable + return Err(anyhow!( + "alias {} has unresolvable recursive definition: {} -> {}", + already_expanded[0], + already_expanded.join(" -> "), + new_cmd, + ) + .into()); + } + + let (expanded_args, _) = expand_aliases(gctx, new_args, already_expanded)?; + return Ok((expanded_args, global_args)); + } + (None, Err(e)) => return Err(e.into()), + } + }; + + Ok((args, GlobalArgs::default())) +} + +#[tracing::instrument(skip_all)] +fn configure_gctx( + gctx: &mut GlobalContext, + args: &ArgMatches, + subcommand_args: Option<&ArgMatches>, + global_args: GlobalArgs, + exec: Option<&Exec>, +) -> CliResult { + let arg_target_dir = &subcommand_args.and_then(|a| a.value_of_path("target-dir", gctx)); + let mut verbose = global_args.verbose + args.verbose(); + // quiet is unusual because it is redefined in some subcommands in order + // to provide custom help text. + let mut quiet = args.flag("quiet") + || subcommand_args.map(|a| a.flag("quiet")).unwrap_or_default() + || global_args.quiet; + if matches!(exec, Some(Exec::Manifest(_))) && !quiet { + // Verbosity is shifted quieter for `Exec::Manifest` as it is can be used as if you ran + // `cargo install` and we especially shouldn't pollute programmatic output. + // + // For now, interactive output has the same default output as `cargo run` but that is + // subject to change. + if let Some(lower) = verbose.checked_sub(1) { + verbose = lower; + } else if !gctx.shell().is_err_tty() { + // Don't pollute potentially-scripted output + quiet = true; + } + } + let global_color = global_args.color; // Extract so it can take reference. + let color = args + .get_one::("color") + .map(String::as_str) + .or_else(|| global_color.as_deref()); + let frozen = args.flag("frozen") || global_args.frozen; + let locked = args.flag("locked") || global_args.locked; + let offline = args.flag("offline") || global_args.offline; + let mut unstable_flags = global_args.unstable_flags; + if let Some(values) = args.get_many::("unstable-features") { + unstable_flags.extend(values.cloned()); + } + let mut config_args = global_args.config_args; + if let Some(values) = args.get_many::("config") { + config_args.extend(values.cloned()); + } + gctx.configure( + verbose, + quiet, + color, + frozen, + locked, + offline, + arg_target_dir, + &unstable_flags, + &config_args, + )?; + Ok(()) +} + +enum Exec { + Builtin(commands::Exec), + Manifest(String), + External(String), +} + +impl Exec { + /// Precedence isn't the most obvious from this function because + /// - Some is determined by `expand_aliases` + /// - Some is enforced by `avoid_ambiguity_between_builtins_and_manifest_commands` + /// + /// In actuality, it is: + /// 1. built-ins xor manifest-command + /// 2. aliases + /// 3. external subcommands + fn infer(cmd: &str) -> CargoResult { + if let Some(exec) = commands::builtin_exec(cmd) { + Ok(Self::Builtin(exec)) + } else if commands::run::is_manifest_command(cmd) { + Ok(Self::Manifest(cmd.to_owned())) + } else { + Ok(Self::External(cmd.to_owned())) + } + } + + #[tracing::instrument(skip_all)] + fn exec(self, gctx: &mut GlobalContext, subcommand_args: &ArgMatches) -> CliResult { + match self { + Self::Builtin(exec) => exec(gctx, subcommand_args), + Self::Manifest(cmd) => { + let ext_path = super::find_external_subcommand(gctx, &cmd); + if !gctx.cli_unstable().script && ext_path.is_some() { + gctx.shell().warn(format_args!( + "\ +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 .", + ))?; + Self::External(cmd).exec(gctx, subcommand_args) + } else { + let ext_args: Vec = subcommand_args + .get_many::("") + .unwrap_or_default() + .cloned() + .collect(); + commands::run::exec_manifest_command(gctx, &cmd, &ext_args) + } + } + Self::External(cmd) => { + let mut ext_args = vec![OsStr::new(&cmd)]; + ext_args.extend( + subcommand_args + .get_many::("") + .unwrap_or_default() + .map(OsString::as_os_str), + ); + super::execute_external_subcommand(gctx, &cmd, &ext_args) + } + } + } +} + +#[derive(Default)] +struct GlobalArgs { + verbose: u32, + quiet: bool, + color: Option, + frozen: bool, + locked: bool, + offline: bool, + unstable_flags: Vec, + config_args: Vec, +} + +impl GlobalArgs { + fn new(args: &ArgMatches) -> GlobalArgs { + GlobalArgs { + verbose: args.verbose(), + quiet: args.flag("quiet"), + color: args.get_one::("color").cloned(), + frozen: args.flag("frozen"), + locked: args.flag("locked"), + offline: args.flag("offline"), + unstable_flags: args + .get_many::("unstable-features") + .unwrap_or_default() + .cloned() + .collect(), + config_args: args + .get_many::("config") + .unwrap_or_default() + .cloned() + .collect(), + } + } +} + +#[tracing::instrument(skip_all)] +pub fn cli(gctx: &GlobalContext) -> Command { + // Don't let config errors get in the way of parsing arguments + let term = gctx.get::("term").unwrap_or_default(); + let color = term + .color + .and_then(|c| c.parse().ok()) + .unwrap_or(ColorChoice::CargoAuto); + let color = match color { + ColorChoice::Always => clap::ColorChoice::Always, + ColorChoice::Never => clap::ColorChoice::Never, + ColorChoice::CargoAuto => clap::ColorChoice::Auto, + }; + + let usage = if is_rustup() { + color_print::cstr!("cargo [+toolchain] [OPTIONS] [COMMAND]\n cargo [+toolchain] [OPTIONS] -Zscript <> [ARGS]...") + } else { + color_print::cstr!("cargo [OPTIONS] [COMMAND]\n cargo [OPTIONS] -Zscript <> [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. + // + // We also want these to come before auto-generated `--help` + .next_display_order(800) + .allow_external_subcommands(true) + .color(color) + .styles(styles) + // Provide a custom help subcommand for calling into man pages + .disable_help_subcommand(true) + .override_usage(usage) + .help_template(color_print::cstr!( + "\ +Rust's package manager + +Usage: {usage} + +Options: +{options} + +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 + 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 + uninstall Uninstall a Rust binary + ... See all commands with --list + +See 'cargo help <>' 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", + "Provide a detailed explanation of a rustc error message", + ) + .value_name("CODE"), + ) + .arg( + opt( + "verbose", + "Use verbose output (-vv very verbose/build.rs output)", + ) + .short('v') + .action(ArgAction::Count) + .global(true), + ) + .arg(flag("quiet", "Do not print cargo log messages").short('q').global(true)) + .arg( + opt("color", "Coloring: auto, always, never") + .value_name("WHEN") + .global(true), + ) + .arg( + Arg::new("directory") + .help("Change to DIRECTORY before doing anything (nightly-only)") + .short('C') + .value_name("DIRECTORY") + .value_hint(clap::ValueHint::DirPath) + .value_parser(clap::builder::ValueParser::path_buf()), + ) + .arg( + flag("locked", "Assert that `Cargo.lock` will remain unchanged") + .help_heading(heading::MANIFEST_OPTIONS) + .global(true), + ) + .arg( + flag("offline", "Run without accessing the network") + .help_heading(heading::MANIFEST_OPTIONS) + .global(true), + ) + .arg( + flag("frozen", "Equivalent to specifying both --locked and --offline") + .help_heading(heading::MANIFEST_OPTIONS) + .global(true), + ) + // Better suggestion for the unsupported short config flag. + .arg( Arg::new("unsupported-short-config-flag") + .help("") + .short('c') + .value_parser(UnknownArgumentValueParser::suggest_arg("--config")) + .action(ArgAction::SetTrue) + .global(true) + .hide(true)) + .arg(multi_opt("config", "KEY=VALUE|PATH", "Override a configuration value").global(true)) + // Better suggestion for the unsupported lowercase unstable feature flag. + .arg( Arg::new("unsupported-lowercase-unstable-feature-flag") + .help("") + .short('z') + .value_parser(UnknownArgumentValueParser::suggest_arg("-Z")) + .action(ArgAction::SetTrue) + .global(true) + .hide(true)) + .arg(Arg::new("unstable-features") + .help("Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details") + .short('Z') + .value_name("FLAG") + .action(ArgAction::Append) + .global(true) + .add(clap_complete::ArgValueCandidates::new(|| { + let flags = CliUnstable::help(); + flags.into_iter().map(|flag| { + clap_complete::CompletionCandidate::new(flag.0.replace("_", "-")).help(flag.1.map(|help| { + help.into() + })) + }).collect() + }))) + .subcommands(commands::builtin()) +} + +#[test] +fn verify_cli() { + let gctx = GlobalContext::default().unwrap(); + cli(&gctx).debug_assert(); +} + +#[test] +fn avoid_ambiguity_between_builtins_and_manifest_commands() { + for cmd in commands::builtin() { + let name = cmd.get_name(); + assert!( + !commands::run::is_manifest_command(&name), + "built-in command {name} is ambiguous with manifest-commands" + ) + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/add.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/add.rs new file mode 100644 index 000000000..263b29b1f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/add.rs @@ -0,0 +1,409 @@ +use cargo::sources::CRATES_IO_REGISTRY; +use cargo::util::print_available_packages; +use indexmap::IndexMap; +use indexmap::IndexSet; + +use cargo::core::dependency::DepKind; +use cargo::core::FeatureValue; +use cargo::ops::cargo_add::add; +use cargo::ops::cargo_add::AddOptions; +use cargo::ops::cargo_add::DepOp; +use cargo::ops::resolve_ws; +use cargo::util::command_prelude::*; +use cargo::util::interning::InternedString; +use cargo::util::toml_mut::manifest::DepTable; +use cargo::CargoResult; + +pub fn cli() -> Command { + clap::Command::new("add") + .about("Add dependencies to a Cargo.toml manifest file") + .override_usage( + color_print::cstr!("\ + cargo add [OPTIONS] <>[@<>] ... + cargo add [OPTIONS] --path <> ... + cargo add [OPTIONS] --git <> ..." + )) + .after_help(color_print::cstr!("Run `cargo help add` for more detailed information.\n")) + .group(clap::ArgGroup::new("selected").multiple(true).required(true)) + .args([ + clap::Arg::new("crates") + .value_name("DEP_ID") + .num_args(0..) + .help("Reference to a package to add as a dependency") + .long_help( + "Reference to a package to add as a dependency + +You can reference a package by: +- ``, like `cargo add serde` (latest version will be used) +- `@`, like `cargo add serde@1` or `cargo add serde@=1.0.38`" + ) + .group("selected"), + flag("no-default-features", + "Disable the default features"), + flag("default-features", + "Re-enable the default features") + .overrides_with("no-default-features"), + clap::Arg::new("features") + .short('F') + .long("features") + .value_name("FEATURES") + .action(ArgAction::Append) + .help("Space or comma separated list of features to activate"), + flag("optional", + "Mark the dependency as optional") + .long_help("Mark the dependency as optional + +The package name will be exposed as feature of your crate.") + .conflicts_with("dev"), + flag("no-optional", + "Mark the dependency as required") + .long_help("Mark the dependency as required + +The package will be removed from your features.") + .conflicts_with("dev") + .overrides_with("optional"), + flag("public", "Mark the dependency as public (unstable)") + .conflicts_with("dev") + .conflicts_with("build") + .long_help("Mark the dependency as public (unstable) + +The dependency can be referenced in your library's public API."), + flag("no-public", "Mark the dependency as private (unstable)") + .conflicts_with("dev") + .conflicts_with("build") + .overrides_with("public") + .long_help("Mark the dependency as private (unstable) + +While you can use the crate in your implementation, it cannot be referenced in your public API."), + clap::Arg::new("rename") + .long("rename") + .action(ArgAction::Set) + .value_name("NAME") + .help("Rename the dependency") + .long_help("Rename the dependency + +Example uses: +- Depending on multiple versions of a crate +- Depend on crates with the same name from different registries"), + ]) + .arg_manifest_path_without_unsupported_path_tip() + .arg_lockfile_path() + .arg_package("Package to modify") + .arg_ignore_rust_version() + .arg_dry_run("Don't actually write the manifest") + .arg_silent_suggestion() + .next_help_heading("Source") + .args([ + clap::Arg::new("path") + .long("path") + .action(ArgAction::Set) + .value_name("PATH") + .help("Filesystem path to local crate to add") + .group("selected") + .conflicts_with("git"), + clap::Arg::new("base") + .long("base") + .action(ArgAction::Set) + .value_name("BASE") + .help("The path base to use when adding from a local crate (unstable).") + .requires("path"), + clap::Arg::new("git") + .long("git") + .action(ArgAction::Set) + .value_name("URI") + .help("Git repository location") + .long_help("Git repository location + +Without any other information, cargo will use latest commit on the main branch.") + .group("selected"), + clap::Arg::new("branch") + .long("branch") + .action(ArgAction::Set) + .value_name("BRANCH") + .help("Git branch to download the crate from") + .requires("git") + .group("git-ref"), + clap::Arg::new("tag") + .long("tag") + .action(ArgAction::Set) + .value_name("TAG") + .help("Git tag to download the crate from") + .requires("git") + .group("git-ref"), + clap::Arg::new("rev") + .long("rev") + .action(ArgAction::Set) + .value_name("REV") + .help("Git reference to download the crate from") + .long_help("Git reference to download the crate from + +This is the catch all, handling hashes to named references in remote repositories.") + .requires("git") + .group("git-ref"), + clap::Arg::new("registry") + .long("registry") + .action(ArgAction::Set) + .value_name("NAME") + .help("Package registry for this dependency") + .add(clap_complete::ArgValueCandidates::new(|| { + let candidates = get_registry_candidates(); + candidates.unwrap_or_default() + })), + ]) + .next_help_heading("Section") + .args([ + flag("dev", + "Add as development dependency") + .long_help("Add as development dependency + +Dev-dependencies are not used when compiling a package for building, but are used for compiling tests, examples, and benchmarks. + +These dependencies are not propagated to other packages which depend on this package.") + .group("section"), + flag("build", + "Add as build dependency") + .long_help("Add as build dependency + +Build-dependencies are the only dependencies available for use by build scripts (`build.rs` files).") + .group("section"), + clap::Arg::new("target") + .long("target") + .action(ArgAction::Set) + .value_name("TARGET") + .value_parser(clap::builder::NonEmptyStringValueParser::new()) + .help("Add as dependency to the given target platform") + ]) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let dry_run = args.dry_run(); + let section = parse_section(args); + + let ws = args.workspace(gctx)?; + + if args.is_present_with_zero_values("package") { + print_available_packages(&ws)?; + } + + let packages = args.packages_from_flags()?; + let packages = packages.get_packages(&ws)?; + let spec = match packages.len() { + 0 => { + return Err(CliError::new( + anyhow::format_err!( + "no packages selected to modify. Please specify one with `-p `" + ), + 101, + )); + } + 1 => packages[0], + _ => { + let names = packages.iter().map(|p| p.name()).collect::>(); + return Err(CliError::new( + anyhow::format_err!( + "`cargo add` could not determine which package to modify. \ + Use the `--package` option to specify a package. \n\ + available packages: {}", + names.join(", ") + ), + 101, + )); + } + }; + + let dependencies = parse_dependencies(gctx, args)?; + + let honor_rust_version = args.honor_rust_version(); + + let options = AddOptions { + gctx, + spec, + dependencies, + section, + dry_run, + honor_rust_version, + }; + add(&ws, &options)?; + + // Reload the workspace since we've changed dependencies + let ws = args.workspace(gctx)?; + resolve_ws(&ws, dry_run)?; + + Ok(()) +} + +fn parse_dependencies(gctx: &GlobalContext, matches: &ArgMatches) -> CargoResult> { + let path = matches.get_one::("path"); + let base = matches.get_one::("base"); + let git = matches.get_one::("git"); + let branch = matches.get_one::("branch"); + let rev = matches.get_one::("rev"); + let tag = matches.get_one::("tag"); + let rename = matches.get_one::("rename"); + let registry = match matches.registry(gctx)? { + Some(reg) if reg == CRATES_IO_REGISTRY => None, + reg => reg, + }; + let default_features = default_features(matches); + let optional = optional(matches); + let public = public(matches); + + let mut crates = matches + .get_many::("crates") + .into_iter() + .flatten() + .map(|c| (Some(c.clone()), None)) + .collect::>(); + + let mut infer_crate_name = false; + + for (crate_name, _) in crates.iter() { + let crate_name = crate_name.as_ref().unwrap(); + + if let Some(toolchain) = crate_name.strip_prefix("+") { + anyhow::bail!( + "invalid character `+` in dependency name: `+{toolchain}` + Use `cargo +{toolchain} add` if you meant to use the `{toolchain}` toolchain." + ); + } + } + + if crates.is_empty() { + if path.is_some() || git.is_some() { + crates.insert(None, None); + infer_crate_name = true; + } else { + unreachable!("clap should ensure we have some source selected"); + } + } + for feature in matches + .get_many::("features") + .into_iter() + .flatten() + .map(String::as_str) + .flat_map(parse_feature) + { + let parsed_value = FeatureValue::new(InternedString::new(feature)); + match parsed_value { + FeatureValue::Feature(_) => { + if 1 < crates.len() { + let candidates = crates + .keys() + .map(|c| { + format!( + "`{}/{}`", + c.as_deref().expect("only none when there is 1"), + feature + ) + }) + .collect::>(); + anyhow::bail!("feature `{feature}` must be qualified by the dependency it's being activated for, like {}", candidates.join(", ")); + } + crates + .first_mut() + .expect("always at least one crate") + .1 + .get_or_insert_with(IndexSet::new) + .insert(feature.to_owned()); + } + FeatureValue::Dep { .. } => { + anyhow::bail!("feature `{feature}` is not allowed to use explicit `dep:` syntax",) + } + FeatureValue::DepFeature { + dep_name, + dep_feature, + .. + } => { + if infer_crate_name { + anyhow::bail!("`{feature}` is unsupported when inferring the crate name, use `{dep_feature}`"); + } + if dep_feature.contains('/') { + anyhow::bail!("multiple slashes in feature `{feature}` is not allowed"); + } + crates.get_mut(&Some(dep_name.as_str().to_owned())).ok_or_else(|| { + anyhow::format_err!("feature `{dep_feature}` activated for crate `{dep_name}` but the crate wasn't specified") + })? + .get_or_insert_with(IndexSet::new) + .insert(dep_feature.as_str().to_owned()); + } + } + } + + let mut deps: Vec = Vec::new(); + for (crate_spec, features) in crates { + let dep = DepOp { + crate_spec, + rename: rename.map(String::from), + features, + default_features, + optional, + public, + registry: registry.clone(), + path: path.map(String::from), + base: base.map(String::from), + git: git.map(String::from), + branch: branch.map(String::from), + rev: rev.map(String::from), + tag: tag.map(String::from), + }; + deps.push(dep); + } + + if deps.len() > 1 && rename.is_some() { + anyhow::bail!("cannot specify multiple crates with `--rename`"); + } + + Ok(deps) +} + +fn default_features(matches: &ArgMatches) -> Option { + resolve_bool_arg( + matches.flag("default-features"), + matches.flag("no-default-features"), + ) +} + +fn optional(matches: &ArgMatches) -> Option { + resolve_bool_arg(matches.flag("optional"), matches.flag("no-optional")) +} + +fn public(matches: &ArgMatches) -> Option { + resolve_bool_arg(matches.flag("public"), matches.flag("no-public")) +} + +fn resolve_bool_arg(yes: bool, no: bool) -> Option { + match (yes, no) { + (true, false) => Some(true), + (false, true) => Some(false), + (false, false) => None, + (_, _) => unreachable!("clap should make this impossible"), + } +} + +fn parse_section(matches: &ArgMatches) -> DepTable { + let kind = if matches.flag("dev") { + DepKind::Development + } else if matches.flag("build") { + DepKind::Build + } else { + DepKind::Normal + }; + + let mut table = DepTable::new().set_kind(kind); + + if let Some(target) = matches.get_one::("target") { + assert!(!target.is_empty(), "Target specification may not be empty"); + table = table.set_target(target); + } + + table +} + +/// Split feature flag list +fn parse_feature(feature: &str) -> impl Iterator { + // Not re-using `CliFeatures` because it uses a BTreeSet and loses user's ordering + feature + .split_whitespace() + .flat_map(|s| s.split(',')) + .filter(|s| !s.is_empty()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/bench.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/bench.rs new file mode 100644 index 000000000..2d3a726f4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/bench.rs @@ -0,0 +1,80 @@ +use crate::command_prelude::*; +use cargo::ops::{self, TestOptions}; + +pub fn cli() -> Command { + subcommand("bench") + .about("Execute all benchmarks of a local package") + .next_display_order(0) + .arg( + Arg::new("BENCHNAME") + .action(ArgAction::Set) + .help("If specified, only run benches containing this string in their names"), + ) + .arg( + Arg::new("args") + .value_name("ARGS") + .help("Arguments for the bench binary") + .num_args(0..) + .last(true), + ) + .arg(flag("no-run", "Compile, but don't run benchmarks")) + .arg(flag( + "no-fail-fast", + "Run all benchmarks regardless of failure", + )) + .arg_message_format() + .arg_silent_suggestion() + .arg_package_spec( + "Package to run benchmarks for", + "Benchmark all packages in the workspace", + "Exclude packages from the benchmark", + ) + .arg_targets_all( + "Benchmark only this package's library", + "Benchmark only the specified binary", + "Benchmark all binaries", + "Benchmark only the specified example", + "Benchmark all examples", + "Benchmark only the specified test target", + "Benchmark all targets that have `test = true` set", + "Benchmark only the specified bench target", + "Benchmark all targets that have `bench = true` set", + "Benchmark all targets", + ) + .arg_features() + .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() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help bench` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + + let mut compile_opts = + args.compile_options(gctx, CompileMode::Bench, Some(&ws), ProfileChecking::Custom)?; + + compile_opts.build_config.requested_profile = + args.get_profile_name("bench", ProfileChecking::Custom)?; + + let ops = TestOptions { + no_run: args.flag("no-run"), + no_fail_fast: args.flag("no-fail-fast"), + compile_opts, + }; + + let bench_args = args.get_one::("BENCHNAME").into_iter(); + let bench_args = bench_args.chain(args.get_many::("args").unwrap_or_default()); + let bench_args = bench_args.map(String::as_str).collect::>(); + + ops::run_benches(&ws, &ops, &bench_args) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/build.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/build.rs new file mode 100644 index 000000000..f03889492 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/build.rs @@ -0,0 +1,82 @@ +use crate::command_prelude::*; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("build") + // subcommand aliases are handled in aliased_command() + // .alias("b") + .about("Compile a local package and all of its dependencies") + .arg_future_incompat_report() + .arg_message_format() + .arg_silent_suggestion() + .arg_package_spec( + "Package to build (see `cargo help pkgid`)", + "Build all packages in the workspace", + "Exclude packages from the build", + ) + .arg_targets_all( + "Build only this package's library", + "Build only the specified binary", + "Build all binaries", + "Build only the specified example", + "Build all examples", + "Build only the specified test target", + "Build all targets that have `test = true` set", + "Build only the specified bench target", + "Build all targets that have `bench = true` set", + "Build all targets", + ) + .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_parallel() + .arg_target_triple("Build for the target triple") + .arg_target_dir() + .arg_artifact_dir() + .arg_build_plan() + .arg_unit_graph() + .arg_timings() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help build` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + let mut compile_opts = + args.compile_options(gctx, CompileMode::Build, Some(&ws), ProfileChecking::Custom)?; + + 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("--artifact-dir", 6790)?; + } + + ops::compile(&ws, &compile_opts)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/check.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/check.rs new file mode 100644 index 000000000..e528dac29 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/check.rs @@ -0,0 +1,59 @@ +use crate::command_prelude::*; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("check") + // subcommand aliases are handled in aliased_command() + // .alias("c") + .about("Check a local package and all of its dependencies for errors") + .arg_future_incompat_report() + .arg_message_format() + .arg_silent_suggestion() + .arg_package_spec( + "Package(s) to check", + "Check all packages in the workspace", + "Exclude packages from the check", + ) + .arg_targets_all( + "Check only this package's library", + "Check only the specified binary", + "Check all binaries", + "Check only the specified example", + "Check all examples", + "Check only the specified test target", + "Check all targets that have `test = true` set", + "Check only the specified bench target", + "Check all targets that have `bench = true` set", + "Check all targets", + ) + .arg_features() + .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") + .arg_target_dir() + .arg_unit_graph() + .arg_timings() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help check` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + // This is a legacy behavior that causes `cargo check` to pass `--test`. + let test = matches!( + args.get_one::("profile").map(String::as_str), + Some("test") + ); + let mode = CompileMode::Check { test }; + let compile_opts = + args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?; + + ops::compile(&ws, &compile_opts)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/clean.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/clean.rs new file mode 100644 index 000000000..d9414b4d1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/clean.rs @@ -0,0 +1,198 @@ +use crate::command_prelude::*; +use crate::util::cache_lock::CacheLockMode; +use cargo::core::gc::Gc; +use cargo::core::gc::{parse_human_size, parse_time_span, GcOpts}; +use cargo::core::global_cache_tracker::GlobalCacheTracker; +use cargo::ops::CleanContext; +use cargo::ops::{self, CleanOptions}; +use cargo::util::print_available_packages; +use std::time::Duration; + +pub fn cli() -> Command { + subcommand("clean") + .about("Remove artifacts that cargo has generated in the past") + .arg_doc("Whether or not to clean just the documentation directory") + .arg_silent_suggestion() + .arg_package_spec_simple("Package to clean artifacts for") + .arg_release("Whether or not to clean release artifacts") + .arg_profile("Clean artifacts of the specified profile") + .arg_target_triple("Target triple to clean output for") + .arg_target_dir() + .arg_manifest_path() + .arg_lockfile_path() + .arg_dry_run("Display what would be deleted without deleting anything") + .args_conflicts_with_subcommands(true) + .subcommand( + subcommand("gc") + .about("Clean global caches") + .hide(true) + .arg_silent_suggestion() + .arg_dry_run("Display what would be deleted without deleting anything") + // NOTE: Not all of these options may get stabilized. Some of them are + // very low-level details, and may not be something typical users need. + .arg( + opt( + "max-src-age", + "Deletes source cache files that have not been used \ + since the given age (unstable)", + ) + .value_name("DURATION") + .value_parser(parse_time_span), + ) + .arg( + opt( + "max-crate-age", + "Deletes crate cache files that have not been used \ + since the given age (unstable)", + ) + .value_name("DURATION") + .value_parser(parse_time_span), + ) + .arg( + opt( + "max-index-age", + "Deletes registry indexes that have not been used \ + since the given age (unstable)", + ) + .value_name("DURATION") + .value_parser(parse_time_span), + ) + .arg( + opt( + "max-git-co-age", + "Deletes git dependency checkouts that have not been used \ + since the given age (unstable)", + ) + .value_name("DURATION") + .value_parser(parse_time_span), + ) + .arg( + opt( + "max-git-db-age", + "Deletes git dependency clones that have not been used \ + since the given age (unstable)", + ) + .value_name("DURATION") + .value_parser(parse_time_span), + ) + .arg( + opt( + "max-download-age", + "Deletes any downloaded cache data that has not been used \ + since the given age (unstable)", + ) + .value_name("DURATION") + .value_parser(parse_time_span), + ) + .arg( + opt( + "max-src-size", + "Deletes source cache files until the cache is under the \ + given size (unstable)", + ) + .value_name("SIZE") + .value_parser(parse_human_size), + ) + .arg( + opt( + "max-crate-size", + "Deletes crate cache files until the cache is under the \ + given size (unstable)", + ) + .value_name("SIZE") + .value_parser(parse_human_size), + ) + .arg( + opt( + "max-git-size", + "Deletes git dependency caches until the cache is under \ + the given size (unstable)", + ) + .value_name("SIZE") + .value_parser(parse_human_size), + ) + .arg( + opt( + "max-download-size", + "Deletes downloaded cache data until the cache is under \ + the given size (unstable)", + ) + .value_name("SIZE") + .value_parser(parse_human_size), + ), + ) + .after_help(color_print::cstr!( + "Run `cargo help clean` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + match args.subcommand() { + Some(("gc", args)) => { + return gc(gctx, args); + } + Some((cmd, _)) => { + unreachable!("unexpected command {}", cmd) + } + None => {} + } + + let ws = args.workspace(gctx)?; + + if args.is_present_with_zero_values("package") { + print_available_packages(&ws)?; + } + + let opts = CleanOptions { + gctx, + spec: values(args, "package"), + targets: args.targets()?, + 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(), + }; + ops::clean(&ws, &opts)?; + Ok(()) +} + +fn gc(gctx: &GlobalContext, args: &ArgMatches) -> CliResult { + gctx.cli_unstable().fail_if_stable_command( + gctx, + "clean gc", + 12633, + "gc", + gctx.cli_unstable().gc, + )?; + + let size_opt = |opt| -> Option { args.get_one::(opt).copied() }; + let duration_opt = |opt| -> Option { args.get_one::(opt).copied() }; + let mut gc_opts = GcOpts { + max_src_age: duration_opt("max-src-age"), + max_crate_age: duration_opt("max-crate-age"), + max_index_age: duration_opt("max-index-age"), + max_git_co_age: duration_opt("max-git-co-age"), + max_git_db_age: duration_opt("max-git-db-age"), + max_src_size: size_opt("max-src-size"), + max_crate_size: size_opt("max-crate-size"), + max_git_size: size_opt("max-git-size"), + max_download_size: size_opt("max-download-size"), + }; + if let Some(age) = duration_opt("max-download-age") { + gc_opts.set_max_download_age(age); + } + // If the user sets any options, then only perform the options requested. + // If no options are set, do the default behavior. + if !gc_opts.is_download_cache_opt_set() { + gc_opts.update_for_auto_gc(gctx)?; + } + + let _lock = gctx.acquire_package_cache_lock(CacheLockMode::MutateExclusive)?; + let mut cache_track = GlobalCacheTracker::new(&gctx)?; + let mut gc = Gc::new(gctx, &mut cache_track)?; + let mut clean_ctx = CleanContext::new(gctx); + clean_ctx.dry_run = args.dry_run(); + gc.gc(&mut clean_ctx, &gc_opts)?; + clean_ctx.display_summary()?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/config.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/config.rs new file mode 100644 index 000000000..ed120143d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/config.rs @@ -0,0 +1,59 @@ +use crate::command_prelude::*; +use cargo::ops::cargo_config; + +pub fn cli() -> Command { + subcommand("config") + .about("Inspect configuration values") + .subcommand_required(true) + .arg_required_else_help(true) + .subcommand( + subcommand("get") + .arg( + Arg::new("key") + .action(ArgAction::Set) + .help("The config key to display"), + ) + .arg( + opt("format", "Display format") + .value_parser(cargo_config::ConfigFormat::POSSIBLE_VALUES) + .default_value("toml"), + ) + .arg(flag( + "show-origin", + "Display where the config value is defined", + )) + .arg( + opt("merged", "Whether or not to merge config values") + .value_parser(["yes", "no"]) + .default_value("yes"), + ), + ) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + gctx.cli_unstable().fail_if_stable_command( + gctx, + "config", + 9301, + "unstable-options", + gctx.cli_unstable().unstable_options, + )?; + match args.subcommand() { + Some(("get", args)) => { + let opts = cargo_config::GetOptions { + key: args.get_one::("key").map(String::as_str), + format: args.get_one::("format").unwrap().parse()?, + show_origin: args.flag("show-origin"), + merged: args.get_one::("merged").map(String::as_str) == Some("yes"), + }; + cargo_config::get(gctx, &opts)?; + } + Some((cmd, _)) => { + unreachable!("unexpected command {}", cmd) + } + None => { + unreachable!("unexpected command") + } + } + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/doc.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/doc.rs new file mode 100644 index 000000000..6707364d9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/doc.rs @@ -0,0 +1,65 @@ +use crate::command_prelude::*; + +use cargo::ops::{self, DocOptions}; + +pub fn cli() -> Command { + subcommand("doc") + // subcommand aliases are handled in aliased_command() + // .alias("d") + .about("Build a package's documentation") + .arg(flag( + "open", + "Opens the docs in a browser after the operation", + )) + .arg(flag( + "no-deps", + "Don't build documentation for dependencies", + )) + .arg(flag("document-private-items", "Document private items")) + .arg_message_format() + .arg_silent_suggestion() + .arg_package_spec( + "Package to document", + "Document all packages in the workspace", + "Exclude packages from the build", + ) + .arg_features() + .arg_targets_lib_bin_example( + "Document only this package's library", + "Document only the specified binary", + "Document all binaries", + "Document only the specified example", + "Document all examples", + ) + .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") + .arg_target_dir() + .arg_unit_graph() + .arg_timings() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help doc` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + let mode = CompileMode::Doc { + deps: !args.flag("no-deps"), + json: false, + }; + let mut compile_opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::Custom)?; + compile_opts.rustdoc_document_private_items = args.flag("document-private-items"); + + let doc_opts = DocOptions { + open_result: args.flag("open"), + output_format: ops::OutputFormat::Html, + compile_opts, + }; + ops::doc(&ws, &doc_opts)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fetch.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fetch.rs new file mode 100644 index 000000000..2fdba80ba --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fetch.rs @@ -0,0 +1,27 @@ +use crate::command_prelude::*; + +use cargo::ops; +use cargo::ops::FetchOptions; + +pub fn cli() -> Command { + subcommand("fetch") + .about("Fetch dependencies of a package from the network") + .arg_silent_suggestion() + .arg_target_triple("Fetch dependencies for the target triple") + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help fetch` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + + let opts = FetchOptions { + gctx, + targets: args.targets()?, + }; + let _ = ops::fetch(&ws, &opts)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fix.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fix.rs new file mode 100644 index 000000000..38bd75497 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/fix.rs @@ -0,0 +1,107 @@ +use crate::command_prelude::*; +use cargo::core::Workspace; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("fix") + .about("Automatically fix lint warnings reported by rustc") + .arg(flag("edition", "Fix in preparation for the next edition")) + .arg(flag( + "edition-idioms", + "Fix warnings to migrate to the idioms of an edition", + )) + .arg(flag( + "broken-code", + "Fix code even if it already has compiler errors", + )) + .arg(flag( + "allow-no-vcs", + "Fix code even if a VCS was not detected", + )) + .arg(flag( + "allow-dirty", + "Fix code even if the working directory is dirty or has staged changes", + )) + .arg(flag( + "allow-staged", + "Fix code even if the working directory has staged changes", + )) + .arg_message_format() + .arg_silent_suggestion() + .arg_package_spec( + "Package(s) to fix", + "Fix all packages in the workspace", + "Exclude packages from the fixes", + ) + .arg_targets_all( + "Fix only this package's library", + "Fix only the specified binary", + "Fix all binaries", + "Fix only the specified example", + "Fix all examples", + "Fix only the specified test target", + "Fix all targets that have `test = true` set", + "Fix only the specified bench target", + "Fix all targets that have `bench = true` set", + "Fix all targets (default)", + ) + .arg_features() + .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() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help fix` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + // This is a legacy behavior that causes `cargo fix` to pass `--test`. + let test = matches!( + args.get_one::("profile").map(String::as_str), + Some("test") + ); + let mode = CompileMode::Check { test }; + + // Unlike other commands default `cargo fix` to all targets to fix as much + // code as we can. + let root_manifest = args.root_manifest(gctx)?; + + // Can't use workspace() to avoid using -Zavoid-dev-deps (if passed) + let mut ws = Workspace::new(&root_manifest, gctx)?; + ws.set_resolve_honors_rust_version(args.honor_rust_version()); + let lockfile_path = args.lockfile_path(gctx)?; + ws.set_requested_lockfile_path(lockfile_path.clone()); + + let mut opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?; + + if !opts.filter.is_specific() { + // cargo fix with no target selection implies `--all-targets`. + opts.filter = ops::CompileFilter::new_all_targets(); + } + + let allow_dirty = args.flag("allow-dirty"); + + ops::fix( + gctx, + &ws, + &root_manifest, + &mut ops::FixOptions { + edition: args.flag("edition"), + idioms: args.flag("edition-idioms"), + compile_opts: opts, + allow_dirty, + allow_staged: allow_dirty || args.flag("allow-staged"), + allow_no_vcs: args.flag("allow-no-vcs"), + broken_code: args.flag("broken-code"), + requested_lockfile_path: lockfile_path, + }, + )?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/generate_lockfile.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/generate_lockfile.rs new file mode 100644 index 000000000..1f0be40fb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/generate_lockfile.rs @@ -0,0 +1,21 @@ +use crate::command_prelude::*; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("generate-lockfile") + .about("Generate the lockfile for a package") + .arg_silent_suggestion() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version_with_help("Ignore `rust-version` specification in packages") + .after_help(color_print::cstr!( + "Run `cargo help generate-lockfile` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + ops::generate_lockfile(&ws)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/git_checkout.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/git_checkout.rs new file mode 100644 index 000000000..3dff2657f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/git_checkout.rs @@ -0,0 +1,16 @@ +//! Removed. + +use crate::command_prelude::*; + +const REMOVED: &str = "The `git-checkout` command has been removed."; + +pub fn cli() -> Command { + subcommand("git-checkout") + .about("REMOVED: This command has been removed") + .hide(true) + .override_help(REMOVED) +} + +pub fn exec(_gctx: &mut GlobalContext, _args: &ArgMatches) -> CliResult { + Err(anyhow::format_err!(REMOVED).into()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/help.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/help.rs new file mode 100644 index 000000000..f9f91cf72 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/help.rs @@ -0,0 +1,159 @@ +use crate::aliased_command; +use crate::command_prelude::*; +use cargo::drop_println; +use cargo::util::errors::CargoResult; +use cargo_util::paths::resolve_executable; +use flate2::read::GzDecoder; +use std::ffi::OsStr; +use std::ffi::OsString; +use std::io::Read; +use std::io::Write; +use std::path::Path; + +const COMPRESSED_MAN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/man.tgz")); + +pub fn cli() -> Command { + subcommand("help") + .about("Displays help for a cargo subcommand") + .arg(Arg::new("COMMAND").action(ArgAction::Set).add( + clap_complete::ArgValueCandidates::new(|| { + super::builtin() + .iter() + .map(|cmd| { + let name = cmd.get_name(); + clap_complete::CompletionCandidate::new(name) + .help(cmd.get_about().cloned()) + .hide(cmd.is_hide_set()) + }) + .collect() + }), + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let subcommand = args.get_one::("COMMAND"); + if let Some(subcommand) = subcommand { + if !try_help(gctx, subcommand)? { + match check_builtin(&subcommand) { + Some(s) => { + crate::execute_internal_subcommand( + gctx, + &[OsStr::new(s), OsStr::new("--help")], + )?; + } + None => { + crate::execute_external_subcommand( + gctx, + subcommand, + &[OsStr::new(subcommand), OsStr::new("--help")], + )?; + } + } + } + } else { + let mut cmd = crate::cli::cli(gctx); + let _ = cmd.print_help(); + } + Ok(()) +} + +fn try_help(gctx: &GlobalContext, subcommand: &str) -> CargoResult { + let subcommand = match check_alias(gctx, subcommand) { + // If this alias is more than a simple subcommand pass-through, show the alias. + Some(argv) if argv.len() > 1 => { + let alias = argv.join(" "); + drop_println!(gctx, "`{}` is aliased to `{}`", subcommand, alias); + return Ok(true); + } + // Otherwise, resolve the alias into its subcommand. + Some(argv) => { + // An alias with an empty argv can be created via `"empty-alias" = ""`. + let first = argv.get(0).map(String::as_str).unwrap_or(subcommand); + first.to_string() + } + None => subcommand.to_string(), + }; + + let subcommand = match check_builtin(&subcommand) { + Some(s) => s, + None => return Ok(false), + }; + + if resolve_executable(Path::new("man")).is_ok() { + let man = match extract_man(subcommand, "1") { + Some(man) => man, + None => return Ok(false), + }; + write_and_spawn(subcommand, &man, "man")?; + } else { + let txt = match extract_man(subcommand, "txt") { + Some(txt) => txt, + None => return Ok(false), + }; + if resolve_executable(Path::new("less")).is_ok() { + write_and_spawn(subcommand, &txt, "less")?; + } else if resolve_executable(Path::new("more")).is_ok() { + write_and_spawn(subcommand, &txt, "more")?; + } else { + drop(std::io::stdout().write_all(&txt)); + } + } + Ok(true) +} + +/// Checks if the given subcommand is an alias. +/// +/// Returns None if it is not an alias. +fn check_alias(gctx: &GlobalContext, subcommand: &str) -> Option> { + aliased_command(gctx, subcommand).ok().flatten() +} + +/// Checks if the given subcommand is a built-in command (not via an alias). +/// +/// Returns None if it is not a built-in command. +fn check_builtin(subcommand: &str) -> Option<&str> { + super::builtin_exec(subcommand).map(|_| subcommand) +} + +/// Extracts the given man page from the compressed archive. +/// +/// Returns None if the command wasn't found. +fn extract_man(subcommand: &str, extension: &str) -> Option> { + let extract_name = OsString::from(format!("cargo-{}.{}", subcommand, extension)); + let gz = GzDecoder::new(COMPRESSED_MAN); + let mut ar = tar::Archive::new(gz); + // Unwraps should be safe here, since this is a static archive generated + // by our build script. It should never be an invalid format! + for entry in ar.entries().unwrap() { + let mut entry = entry.unwrap(); + let path = entry.path().unwrap(); + if path.file_name().unwrap() != extract_name { + continue; + } + let mut result = Vec::new(); + entry.read_to_end(&mut result).unwrap(); + return Some(result); + } + None +} + +/// Write the contents of a man page to disk and spawn the given command to +/// display it. +fn write_and_spawn(name: &str, contents: &[u8], command: &str) -> CargoResult<()> { + let prefix = format!("cargo-{}.", name); + let mut tmp = tempfile::Builder::new().prefix(&prefix).tempfile()?; + let f = tmp.as_file_mut(); + f.write_all(contents)?; + f.flush()?; + let path = tmp.path(); + // Use a path relative to the temp directory so that it can work on + // cygwin/msys systems which don't handle windows-style paths. + let mut relative_name = std::ffi::OsString::from("./"); + relative_name.push(path.file_name().unwrap()); + let mut cmd = std::process::Command::new(command) + .arg(relative_name) + .current_dir(path.parent().unwrap()) + .spawn()?; + drop(cmd.wait()); + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/info.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/info.rs new file mode 100644 index 000000000..31b68f3e8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/info.rs @@ -0,0 +1,35 @@ +use anyhow::Context; +use cargo::ops::info; +use cargo::util::command_prelude::*; +use cargo_util_schemas::core::PackageIdSpec; + +pub fn cli() -> Command { + Command::new("info") + .about("Display information about a package") + .arg( + Arg::new("package") + .required(true) + .value_name("SPEC") + .help_heading(heading::PACKAGE_SELECTION) + .help("Package to inspect"), + ) + .arg_index("Registry index URL to search packages in") + .arg_registry("Registry to search packages in") + .arg_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help info` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let package = args + .get_one::("package") + .map(String::as_str) + .unwrap(); + let spec = PackageIdSpec::parse(package) + .with_context(|| format!("invalid package ID specification: `{package}`"))?; + + let reg_or_index = args.registry_or_index(gctx)?; + info(&spec, gctx, reg_or_index)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/init.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/init.rs new file mode 100644 index 000000000..614a20079 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/init.rs @@ -0,0 +1,26 @@ +use crate::command_prelude::*; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("init") + .about("Create a new cargo package in an existing directory") + .arg( + Arg::new("path") + .value_name("PATH") + .action(ArgAction::Set) + .default_value("."), + ) + .arg_new_opts() + .arg_registry("Registry to use") + .arg_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help init` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let opts = args.new_options(gctx)?; + ops::init(&opts, gctx)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/install.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/install.rs new file mode 100644 index 000000000..2b0a77fea --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/install.rs @@ -0,0 +1,316 @@ +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::VersionExt; +use cargo::CargoResult; +use itertools::Itertools; +use semver::VersionReq; + +use cargo_util::paths; + +pub fn cli() -> Command { + subcommand("install") + .about("Install a Rust binary") + .arg( + Arg::new("crate") + .value_name("CRATE[@]") + .help("Select the package from the given source") + .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( + opt("index", "Registry index to install from") + .value_name("INDEX") + .requires("crate") + .conflicts_with_all(&["git", "path", "registry"]), + ) + .arg( + opt("registry", "Registry to use") + .value_name("REGISTRY") + .requires("crate") + .conflicts_with_all(&["git", "path", "index"]), + ) + .arg( + opt("git", "Git URL to install the specified crate from") + .value_name("URL") + .conflicts_with_all(&["path", "index", "registry"]), + ) + .arg( + opt("branch", "Branch to use when installing from git") + .value_name("BRANCH") + .requires("git"), + ) + .arg( + opt("tag", "Tag to use when installing from git") + .value_name("TAG") + .requires("git"), + ) + .arg( + opt("rev", "Specific commit to use when installing from git") + .value_name("SHA") + .requires("git"), + ) + .arg( + opt("path", "Filesystem path to local crate to install from") + .value_name("PATH") + .conflicts_with_all(&["git", "index", "registry"]), + ) + .arg(opt("root", "Directory to install packages into").value_name("DIR")) + .arg(flag("force", "Force overwriting existing crates or binaries").short('f')) + .arg_dry_run("Perform all checks without installing (unstable)") + .arg(flag("no-track", "Do not save tracking information")) + .arg(flag( + "list", + "List all installed packages and their versions", + )) + .arg_ignore_rust_version() + .arg_message_format() + .arg_silent_suggestion() + .arg_targets_bins_examples( + "Install only the specified binary", + "Install all binaries", + "Install only the specified example", + "Install all examples", + ) + .arg_features() + .arg_parallel() + .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") + .arg_target_dir() + .arg_timings() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help install` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let path = args.value_of_path("path", gctx); + if let Some(path) = &path { + gctx.reload_rooted_at(path)?; + } else { + // TODO: Consider calling set_search_stop_path(home). + gctx.reload_rooted_at(gctx.home().clone().into_path_unlocked())?; + } + + // In general, we try to avoid normalizing paths in Cargo, + // but in these particular cases we need it to fix rust-lang/cargo#10283. + // (Handle `SourceId::for_path` and `Workspace::new`, + // but not `GlobalContext::reload_rooted_at` which is always cwd) + let path = path.map(|p| paths::normalize_path(&p)); + + let version = args.get_one::("version"); + let krates = args + .get_many::("crate") + .unwrap_or_default() + .cloned() + .dedup_by(|x, y| x == y) + .map(|(krate, local_version)| resolve_crate(krate, local_version, version)) + .collect::>>()?; + + for (crate_name, _) in krates.iter() { + if let Some(toolchain) = crate_name.strip_prefix("+") { + return Err(anyhow!( + "invalid character `+` in package name: `+{toolchain}` + Use `cargo +{toolchain} install` if you meant to use the `{toolchain}` toolchain." + ) + .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; + + let source = if let Some(url) = args.get_one::("git") { + let url = url.into_url()?; + let gitref = if let Some(branch) = args.get_one::("branch") { + GitReference::Branch(branch.clone()) + } else if let Some(tag) = args.get_one::("tag") { + GitReference::Tag(tag.clone()) + } else if let Some(rev) = args.get_one::("rev") { + GitReference::Rev(rev.clone()) + } else { + GitReference::DefaultBranch + }; + SourceId::for_git(&url, gitref)? + } else if let Some(path) = &path { + SourceId::for_path(path)? + } else if krates.is_empty() { + from_cwd = true; + SourceId::for_path(gctx.cwd())? + } else if let Some(reg_or_index) = args.registry_or_index(gctx)? { + match reg_or_index { + ops::RegistryOrIndex::Registry(r) => SourceId::alt_registry(gctx, &r)?, + ops::RegistryOrIndex::Index(url) => SourceId::for_registry(&url)?, + } + } else { + SourceId::crates_io(gctx)? + }; + + let root = args.get_one::("root").map(String::as_str); + + // We only provide workspace information for local crate installation from + // one of the following sources: + // - From current working directory (only work for edition 2015). + // - From a specific local file path (from `--path` arg). + // + // This workspace information is for emitting helpful messages from + // `ArgMatchesExt::compile_options` and won't affect the actual compilation. + let workspace = if from_cwd { + args.workspace(gctx).ok() + } else if let Some(path) = &path { + Workspace::new(&path.join("Cargo.toml"), gctx).ok() + } else { + None + }; + + let mut compile_opts = args.compile_options( + gctx, + CompileMode::Build, + workspace.as_ref(), + ProfileChecking::Custom, + )?; + + compile_opts.build_config.requested_profile = + args.get_profile_name("release", ProfileChecking::Custom)?; + if args.dry_run() { + gctx.cli_unstable().fail_if_stable_opt("--dry-run", 11123)?; + } + + let requested_lockfile_path = args.lockfile_path(gctx)?; + // 14421: lockfile path should imply --locked on running `install` + if requested_lockfile_path.is_some() { + gctx.set_locked(true); + } + + if args.flag("list") { + ops::install_list(root, gctx)?; + } else { + ops::install( + gctx, + root, + krates, + source, + from_cwd, + &compile_opts, + args.flag("force"), + args.flag("no-track"), + args.dry_run(), + requested_lockfile_path.as_deref(), + )?; + } + Ok(()) +} + +type CrateVersion = (String, Option); + +fn parse_crate(krate: &str) -> crate::CargoResult { + 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 before '@'"); + } + 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 { + // 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::() { + 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.trim().parse::() { + Ok(v) => Ok(v.to_exact_req()), + 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::().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, + version: Option<&VersionReq>, +) -> crate::CargoResult { + let version = match (local_version, version) { + (Some(_), Some(_)) => { + anyhow::bail!("cannot specify both `@` and `--version `"); + } + (Some(l), None) => Some(l), + (None, Some(g)) => Some(g.to_owned()), + (None, None) => None, + }; + Ok((krate, version)) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/locate_project.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/locate_project.rs new file mode 100644 index 000000000..d38d70c0f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/locate_project.rs @@ -0,0 +1,95 @@ +use crate::command_prelude::*; +use anyhow::bail; +use cargo::{drop_println, CargoResult}; +use serde::Serialize; + +pub fn cli() -> Command { + subcommand("locate-project") + .about("Print a JSON representation of a Cargo.toml file's location") + .arg(flag("workspace", "Locate Cargo.toml of the workspace root")) + .arg( + opt( + "message-format", + "Output representation [possible values: json, plain]", + ) + .value_name("FMT"), + ) + .arg_silent_suggestion() + .arg_manifest_path() + .after_help(color_print::cstr!( + "Run `cargo help locate-project` for more detailed information.\n" + )) +} + +#[derive(Serialize)] +pub struct ProjectLocation<'a> { + root: &'a str, +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let root_manifest; + let workspace; + let root = match WhatToFind::parse(args) { + WhatToFind::CurrentManifest => { + root_manifest = args.root_manifest(gctx)?; + &root_manifest + } + WhatToFind::Workspace => { + workspace = args.workspace(gctx)?; + workspace.root_manifest() + } + }; + + let root = root + .to_str() + .ok_or_else(|| { + anyhow::format_err!( + "your package path contains characters \ + not representable in Unicode" + ) + }) + .map_err(|e| CliError::new(e, 1))?; + + let location = ProjectLocation { root }; + + match MessageFormat::parse(args)? { + MessageFormat::Json => gctx.shell().print_json(&location)?, + MessageFormat::Plain => drop_println!(gctx, "{}", location.root), + } + + Ok(()) +} + +enum WhatToFind { + CurrentManifest, + Workspace, +} + +impl WhatToFind { + fn parse(args: &ArgMatches) -> Self { + if args.flag("workspace") { + WhatToFind::Workspace + } else { + WhatToFind::CurrentManifest + } + } +} + +enum MessageFormat { + Json, + Plain, +} + +impl MessageFormat { + fn parse(args: &ArgMatches) -> CargoResult { + let fmt = match args.get_one::("message-format") { + Some(fmt) => fmt, + None => return Ok(MessageFormat::Json), + }; + match fmt.to_ascii_lowercase().as_str() { + "json" => Ok(MessageFormat::Json), + "plain" => Ok(MessageFormat::Plain), + s => bail!("invalid message format specifier: `{}`", s), + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/login.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/login.rs new file mode 100644 index 000000000..7fe86b9b0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/login.rs @@ -0,0 +1,49 @@ +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") + .value_name("TOKEN") + .action(ArgAction::Set) + .hide(true), + ) + .arg_registry("Registry to use") + .arg( + Arg::new("args") + .help("Additional arguments for the credential provider") + .num_args(0..) + .last(true), + ) + .arg_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help login` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let reg = args.registry_or_index(gctx)?; + assert!( + !matches!(reg, Some(RegistryOrIndex::Index(..))), + "must not be index URL" + ); + + let token = args.get_one::("token").map(|s| s.as_str().into()); + if token.is_some() { + let _ = gctx + .shell() + .warn("`cargo login ` is deprecated in favor of reading `` from stdin"); + } + + let extra_args = args + .get_many::("args") + .unwrap_or_default() + .map(String::as_str) + .collect::>(); + ops::registry_login(gctx, token, reg.as_ref(), &extra_args)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/logout.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/logout.rs new file mode 100644 index 000000000..57df53ad7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/logout.rs @@ -0,0 +1,25 @@ +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_registry("Registry to use") + .arg_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help logout` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let reg = args.registry_or_index(gctx)?; + assert!( + !matches!(reg, Some(RegistryOrIndex::Index(..))), + "must not be index URL" + ); + + ops::registry_logout(gctx, reg)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/metadata.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/metadata.rs new file mode 100644 index 000000000..0b98d50a1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/metadata.rs @@ -0,0 +1,60 @@ +use cargo::ops::{self, OutputMetadataOptions}; + +use crate::command_prelude::*; + +pub fn cli() -> Command { + subcommand("metadata") + .about( + "Output the resolved dependencies of a package, \ + the concrete used versions including overrides, \ + in machine-readable format", + ) + .arg(multi_opt( + "filter-platform", + "TRIPLE", + "Only include resolve dependencies matching the given target-triple", + )) + .arg(flag( + "no-deps", + "Output information only about the workspace members \ + and don't fetch dependencies", + )) + .arg( + opt("format-version", "Format version") + .value_name("VERSION") + .value_parser(["1"]), + ) + .arg_silent_suggestion() + .arg_features() + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help metadata` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + + let version = match args.get_one::("format-version") { + None => { + gctx.shell().warn( + "please specify `--format-version` flag explicitly \ + to avoid compatibility problems", + )?; + 1 + } + Some(version) => version.parse().unwrap(), + }; + + let options = OutputMetadataOptions { + cli_features: args.cli_features()?, + no_deps: args.flag("no-deps"), + filter_platforms: args._values_of("filter-platform"), + version, + }; + + let result = ops::output_metadata(&ws, &options)?; + gctx.shell().print_json(&result)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/mod.rs new file mode 100644 index 000000000..b507226f3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/mod.rs @@ -0,0 +1,133 @@ +use crate::command_prelude::*; + +pub fn builtin() -> Vec { + vec![ + add::cli(), + bench::cli(), + build::cli(), + check::cli(), + clean::cli(), + config::cli(), + doc::cli(), + fetch::cli(), + fix::cli(), + generate_lockfile::cli(), + git_checkout::cli(), + help::cli(), + info::cli(), + init::cli(), + install::cli(), + locate_project::cli(), + login::cli(), + logout::cli(), + metadata::cli(), + new::cli(), + owner::cli(), + package::cli(), + pkgid::cli(), + publish::cli(), + read_manifest::cli(), + remove::cli(), + report::cli(), + run::cli(), + rustc::cli(), + rustdoc::cli(), + search::cli(), + test::cli(), + tree::cli(), + uninstall::cli(), + update::cli(), + vendor::cli(), + verify_project::cli(), + version::cli(), + yank::cli(), + ] +} + +pub type Exec = fn(&mut GlobalContext, &ArgMatches) -> CliResult; + +pub fn builtin_exec(cmd: &str) -> Option { + let f = match cmd { + "add" => add::exec, + "bench" => bench::exec, + "build" => build::exec, + "check" => check::exec, + "clean" => clean::exec, + "config" => config::exec, + "doc" => doc::exec, + "fetch" => fetch::exec, + "fix" => fix::exec, + "generate-lockfile" => generate_lockfile::exec, + "git-checkout" => git_checkout::exec, + "help" => help::exec, + "info" => info::exec, + "init" => init::exec, + "install" => install::exec, + "locate-project" => locate_project::exec, + "login" => login::exec, + "logout" => logout::exec, + "metadata" => metadata::exec, + "new" => new::exec, + "owner" => owner::exec, + "package" => package::exec, + "pkgid" => pkgid::exec, + "publish" => publish::exec, + "read-manifest" => read_manifest::exec, + "remove" => remove::exec, + "report" => report::exec, + "run" => run::exec, + "rustc" => rustc::exec, + "rustdoc" => rustdoc::exec, + "search" => search::exec, + "test" => test::exec, + "tree" => tree::exec, + "uninstall" => uninstall::exec, + "update" => update::exec, + "vendor" => vendor::exec, + "verify-project" => verify_project::exec, + "version" => version::exec, + "yank" => yank::exec, + _ => return None, + }; + Some(f) +} + +pub mod add; +pub mod bench; +pub mod build; +pub mod check; +pub mod clean; +pub mod config; +pub mod doc; +pub mod fetch; +pub mod fix; +pub mod generate_lockfile; +pub mod git_checkout; +pub mod help; +pub mod info; +pub mod init; +pub mod install; +pub mod locate_project; +pub mod login; +pub mod logout; +pub mod metadata; +pub mod new; +pub mod owner; +pub mod package; +pub mod pkgid; +pub mod publish; +pub mod read_manifest; +pub mod remove; +pub mod report; +pub mod run; +pub mod rustc; +pub mod rustdoc; +pub mod search; +pub mod test; +pub mod tree; +pub mod uninstall; +pub mod update; +pub mod vendor; +pub mod verify_project; +pub mod version; +pub mod yank; diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/new.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/new.rs new file mode 100644 index 000000000..35a85e049 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/new.rs @@ -0,0 +1,27 @@ +use crate::command_prelude::*; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("new") + .about("Create a new cargo package at ") + .arg( + Arg::new("path") + .value_name("PATH") + .action(ArgAction::Set) + .required(true), + ) + .arg_new_opts() + .arg_registry("Registry to use") + .arg_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help new` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let opts = args.new_options(gctx)?; + + ops::new(&opts, gctx)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/owner.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/owner.rs new file mode 100644 index 000000000..659408758 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/owner.rs @@ -0,0 +1,51 @@ +use crate::command_prelude::*; + +use cargo::ops::{self, OwnersOptions}; +use cargo_credential::Secret; + +pub fn cli() -> Command { + subcommand("owner") + .about("Manage the owners of a crate on the registry") + .arg(Arg::new("crate").value_name("CRATE").action(ArgAction::Set)) + .arg( + multi_opt( + "add", + "LOGIN", + "Name of a user or team to invite as an owner", + ) + .short('a'), + ) + .arg( + multi_opt( + "remove", + "LOGIN", + "Name of a user or team to remove as an owner", + ) + .short('r'), + ) + .arg(flag("list", "List owners of a crate").short('l')) + .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_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help owner` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let opts = OwnersOptions { + krate: args.get_one::("crate").cloned(), + token: args.get_one::("token").cloned().map(Secret::from), + reg_or_index: args.registry_or_index(gctx)?, + to_add: args + .get_many::("add") + .map(|xs| xs.cloned().collect()), + to_remove: args + .get_many::("remove") + .map(|xs| xs.cloned().collect()), + list: args.flag("list"), + }; + ops::modify_owners(gctx, &opts)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/package.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/package.rs new file mode 100644 index 000000000..251fa286e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/package.rs @@ -0,0 +1,92 @@ +use crate::command_prelude::*; + +use cargo::ops::{self, PackageOpts}; + +pub fn cli() -> Command { + subcommand("package") + .about("Assemble the local package into a distributable tarball") + .arg_index("Registry index URL to prepare the package for (unstable)") + .arg_registry("Registry to prepare the package for (unstable)") + .arg( + flag( + "list", + "Print files included in a package without making one", + ) + .short('l'), + ) + .arg(flag( + "no-verify", + "Don't verify the contents by building them", + )) + .arg(flag( + "no-metadata", + "Ignore warnings about a lack of human-usable metadata", + )) + .arg(flag( + "allow-dirty", + "Allow dirty working directories to be packaged", + )) + .arg_silent_suggestion() + .arg_package_spec_no_all( + "Package(s) to assemble", + "Assemble all packages in the workspace", + "Don't assemble specified packages", + ) + .arg_features() + .arg_target_triple("Build for the target triple") + .arg_target_dir() + .arg_parallel() + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help package` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + if args._value_of("registry").is_some() { + gctx.cli_unstable().fail_if_stable_opt_custom_z( + "--registry", + 13947, + "package-workspace", + gctx.cli_unstable().package_workspace, + )?; + } + if args._value_of("index").is_some() { + gctx.cli_unstable().fail_if_stable_opt_custom_z( + "--index", + 13947, + "package-workspace", + gctx.cli_unstable().package_workspace, + )?; + } + let reg_or_index = args.registry_or_index(gctx)?; + let ws = args.workspace(gctx)?; + if ws.root_maybe().is_embedded() { + return Err(anyhow::format_err!( + "{} is unsupported by `cargo package`", + ws.root_manifest().display() + ) + .into()); + } + let specs = args.packages_from_flags()?; + + ops::package( + &ws, + &PackageOpts { + gctx, + verify: !args.flag("no-verify"), + list: args.flag("list"), + check_metadata: !args.flag("no-metadata"), + allow_dirty: args.flag("allow-dirty"), + to_package: specs, + targets: args.targets()?, + jobs: args.jobs()?, + keep_going: args.keep_going(), + cli_features: args.cli_features()?, + reg_or_index, + }, + )?; + + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/pkgid.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/pkgid.rs new file mode 100644 index 000000000..aa98dc5c3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/pkgid.rs @@ -0,0 +1,31 @@ +use crate::command_prelude::*; + +use cargo::ops; +use cargo::util::print_available_packages; + +pub fn cli() -> Command { + subcommand("pkgid") + .about("Print a fully qualified package specification") + .arg(Arg::new("spec").value_name("SPEC").action(ArgAction::Set)) + .arg_silent_suggestion() + .arg_package("Argument to get the package ID specifier for") + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help pkgid` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + if args.is_present_with_zero_values("package") { + print_available_packages(&ws)? + } + let spec = args + .get_one::("spec") + .or_else(|| args.get_one::("package")) + .map(String::as_str); + let spec = ops::pkgid(&ws, spec)?; + cargo::drop_println!(gctx, "{}", spec); + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/publish.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/publish.rs new file mode 100644 index 000000000..42b6377c7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/publish.rs @@ -0,0 +1,84 @@ +use crate::command_prelude::*; + +use cargo::ops::{self, PublishOpts}; + +pub fn cli() -> Command { + subcommand("publish") + .about("Upload a package to the registry") + .arg_dry_run("Perform all checks without uploading") + .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", + "Don't verify the contents by building them", + )) + .arg(flag( + "allow-dirty", + "Allow dirty working directories to be packaged", + )) + .arg_silent_suggestion() + .arg_package_spec_no_all( + "Package(s) to publish", + "Publish all packages in the workspace (unstable)", + "Don't publish specified packages (unstable)", + ) + .arg_features() + .arg_parallel() + .arg_target_triple("Build for the target triple") + .arg_target_dir() + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help publish` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let reg_or_index = args.registry_or_index(gctx)?; + let ws = args.workspace(gctx)?; + if ws.root_maybe().is_embedded() { + return Err(anyhow::format_err!( + "{} is unsupported by `cargo publish`", + ws.root_manifest().display() + ) + .into()); + } + + let unstable = gctx.cli_unstable(); + let enabled = unstable.package_workspace; + if args.get_flag("workspace") { + unstable.fail_if_stable_opt_custom_z("--workspace", 10948, "package-workspace", enabled)?; + } + if args._value_of("exclude").is_some() { + unstable.fail_if_stable_opt_custom_z("--exclude", 10948, "package-workspace", enabled)?; + } + if args._values_of("package").len() > 1 { + unstable.fail_if_stable_opt_custom_z( + "--package (multiple occurrences)", + 10948, + "package-workspace", + enabled, + )?; + } + + ops::publish( + &ws, + &PublishOpts { + gctx, + token: args + .get_one::("token") + .map(|s| s.to_string().into()), + reg_or_index, + verify: !args.flag("no-verify"), + allow_dirty: args.flag("allow-dirty"), + to_publish: args.packages_from_flags()?, + targets: args.targets()?, + jobs: args.jobs()?, + keep_going: args.keep_going(), + dry_run: args.dry_run(), + cli_features: args.cli_features()?, + }, + )?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/read_manifest.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/read_manifest.rs new file mode 100644 index 000000000..c014c99f5 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/read_manifest.rs @@ -0,0 +1,26 @@ +//! Deprecated. + +use crate::command_prelude::*; + +pub fn cli() -> Command { + subcommand("read-manifest") + .hide(true) + .about(color_print::cstr!( + "\ +DEPRECATED: Print a JSON representation of a Cargo.toml manifest. + +Use `cargo metadata --no-deps` instead.\ +" + )) + .arg_silent_suggestion() + .arg_manifest_path() +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + gctx.shell().print_json( + &ws.current()? + .serialized(gctx.cli_unstable(), ws.unstable_features()), + )?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/remove.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/remove.rs new file mode 100644 index 000000000..d65410618 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/remove.rs @@ -0,0 +1,390 @@ +use cargo::core::dependency::DepKind; +use cargo::core::PackageIdSpec; +use cargo::core::PackageIdSpecQuery; +use cargo::core::Resolve; +use cargo::core::Workspace; +use cargo::ops::cargo_remove::remove; +use cargo::ops::cargo_remove::RemoveOptions; +use cargo::ops::resolve_ws; +use cargo::util::command_prelude::*; +use cargo::util::print_available_packages; +use cargo::util::toml_mut::dependency::Dependency; +use cargo::util::toml_mut::dependency::MaybeWorkspace; +use cargo::util::toml_mut::dependency::Source; +use cargo::util::toml_mut::manifest::DepTable; +use cargo::util::toml_mut::manifest::LocalManifest; +use cargo::CargoResult; + +pub fn cli() -> clap::Command { + clap::Command::new("remove") + // Subcommand aliases are handled in `aliased_command()`. + // .alias("rm") + .about("Remove dependencies from a Cargo.toml manifest file") + .args([clap::Arg::new("dependencies") + .action(clap::ArgAction::Append) + .required(true) + .num_args(1..) + .value_name("DEP_ID") + .help("Dependencies to be removed")]) + .arg_dry_run("Don't actually write the manifest") + .arg_silent_suggestion() + .next_help_heading("Section") + .args([ + clap::Arg::new("dev") + .long("dev") + .conflicts_with("build") + .action(clap::ArgAction::SetTrue) + .group("section") + .help("Remove from dev-dependencies"), + clap::Arg::new("build") + .long("build") + .conflicts_with("dev") + .action(clap::ArgAction::SetTrue) + .group("section") + .help("Remove from build-dependencies"), + clap::Arg::new("target") + .long("target") + .num_args(1) + .value_name("TARGET") + .value_parser(clap::builder::NonEmptyStringValueParser::new()) + .help("Remove from target-dependencies"), + ]) + .arg_package("Package to remove from") + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help remove` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let dry_run = args.dry_run(); + + let workspace = args.workspace(gctx)?; + + if args.is_present_with_zero_values("package") { + print_available_packages(&workspace)?; + } + + let packages = args.packages_from_flags()?; + let packages = packages.get_packages(&workspace)?; + let spec = match packages.len() { + 0 => { + return Err(CliError::new( + anyhow::format_err!( + "no packages selected to modify. Please specify one with `-p `" + ), + 101, + )); + } + 1 => packages[0], + _ => { + let names = packages.iter().map(|p| p.name()).collect::>(); + return Err(CliError::new( + anyhow::format_err!( + "`cargo remove` could not determine which package to modify. \ + Use the `--package` option to specify a package. \n\ + available packages: {}", + names.join(", ") + ), + 101, + )); + } + }; + + let dependencies = args + .get_many::("dependencies") + .expect("required(true)") + .cloned() + .collect::>(); + + let section = parse_section(args); + + let options = RemoveOptions { + gctx, + spec, + dependencies, + section, + dry_run, + }; + remove(&options)?; + + if !dry_run { + // Clean up the workspace + gc_workspace(&workspace)?; + + // Reload the workspace since we've changed dependencies + let ws = args.workspace(gctx)?; + let resolve = { + // HACK: Avoid unused patch warnings by temporarily changing the verbosity. + // In rare cases, this might cause index update messages to not show up + let verbosity = ws.gctx().shell().verbosity(); + ws.gctx() + .shell() + .set_verbosity(cargo::core::Verbosity::Quiet); + let resolve = resolve_ws(&ws, dry_run); + ws.gctx().shell().set_verbosity(verbosity); + resolve?.1 + }; + + // 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, dry_run)?; + } + } + Ok(()) +} + +fn parse_section(args: &ArgMatches) -> DepTable { + let dev = args.flag("dev"); + let build = args.flag("build"); + + let kind = if dev { + DepKind::Development + } else if build { + DepKind::Build + } else { + DepKind::Normal + }; + + let mut table = DepTable::new().set_kind(kind); + + if let Some(target) = args.get_one::("target") { + assert!(!target.is_empty(), "Target specification may not be empty"); + table = table.set_target(target); + } + + table +} + +/// Clean up the workspace.dependencies, profile, patch, and replace sections of the root manifest +/// by removing dependencies which no longer have a reference to them. +fn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> { + let mut workspace_manifest = LocalManifest::try_new(workspace.root_manifest())?; + let mut is_modified = true; + + let members = workspace + .members() + .map(|p| { + Ok(( + LocalManifest::try_new(p.manifest_path())?, + p.manifest().unstable_features(), + )) + }) + .collect::>>()?; + + let mut dependencies = members + .into_iter() + .flat_map(|(member_manifest, unstable_features)| { + member_manifest + .get_sections() + .into_iter() + .flat_map(move |(_, table)| { + table + .as_table_like() + .unwrap() + .iter() + .map(|(key, item)| { + Dependency::from_toml( + workspace.gctx(), + workspace.root(), + &member_manifest.path, + &unstable_features, + key, + item, + ) + }) + .collect::>() + }) + }) + .collect::>>()?; + + // Clean up the workspace.dependencies section and replace instances of + // workspace dependencies with their definitions + if let Some(toml_edit::Item::Table(deps_table)) = workspace_manifest + .data + .get_mut("workspace") + .and_then(|t| t.get_mut("dependencies")) + { + deps_table.set_implicit(true); + for (key, item) in deps_table.iter_mut() { + let ws_dep = Dependency::from_toml( + workspace.gctx(), + workspace.root(), + &workspace.root(), + workspace.unstable_features(), + key.get(), + item, + )?; + + // search for uses of this workspace dependency + let mut is_used = false; + for dep in dependencies.iter_mut().filter(|d| { + d.toml_key() == key.get() && matches!(d.source(), Some(Source::Workspace(_))) + }) { + // HACK: Replace workspace references in `dependencies` to simplify later GC steps: + // 1. Avoid having to look it up again to determine the dependency source / spec + // 2. The entry might get deleted, preventing us from looking it up again + // + // This does lose extra information, like features enabled, but that shouldn't be a + // problem for GC + *dep = ws_dep.clone(); + + is_used = true; + } + + if !is_used { + *item = toml_edit::Item::None; + is_modified = true; + } + } + } + + // Clean up the profile section + // + // Example tables: + // - profile.dev.package.foo + // - profile.release.package."foo:2.1.0" + if let Some(toml_edit::Item::Table(profile_section_table)) = + workspace_manifest.data.get_mut("profile") + { + profile_section_table.set_implicit(true); + + for (_, item) in profile_section_table.iter_mut() { + if let toml_edit::Item::Table(profile_table) = item { + profile_table.set_implicit(true); + + if let Some(toml_edit::Item::Table(package_table)) = + profile_table.get_mut("package") + { + 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)?, + &dependencies, + workspace.gctx(), + )? { + *item = toml_edit::Item::None; + is_modified = true; + } + } + } + } + } + } + + // Clean up the replace section + if let Some(toml_edit::Item::Table(table)) = workspace_manifest.data.get_mut("replace") { + table.set_implicit(true); + + for (key, item) in table.iter_mut() { + if !spec_has_match( + &PackageIdSpec::parse(key.get())?, + &dependencies, + workspace.gctx(), + )? { + *item = toml_edit::Item::None; + is_modified = true; + } + } + } + + if is_modified { + workspace_manifest.write()?; + } + + Ok(()) +} + +/// Check whether or not a package ID spec matches any non-workspace dependencies. +fn spec_has_match( + spec: &PackageIdSpec, + dependencies: &[Dependency], + gctx: &GlobalContext, +) -> CargoResult { + for dep in dependencies { + if spec.name() != &dep.name { + continue; + } + + let version_matches = match (spec.version(), dep.version()) { + (Some(v), Some(vq)) => semver::VersionReq::parse(vq)?.matches(&v), + (Some(_), None) => false, + (None, None | Some(_)) => true, + }; + if !version_matches { + continue; + } + + match dep.source_id(gctx)? { + MaybeWorkspace::Other(source_id) => { + if spec.url().map(|u| u == source_id.url()).unwrap_or(true) { + return Ok(true); + } + } + MaybeWorkspace::Workspace(_) => {} + } + } + + Ok(false) +} + +/// Removes unused patches from the manifest +fn gc_unused_patches(workspace: &Workspace<'_>, resolve: &Resolve) -> CargoResult { + let mut workspace_manifest = LocalManifest::try_new(workspace.root_manifest())?; + let mut modified = false; + + // Clean up the patch section + if let Some(toml_edit::Item::Table(patch_section_table)) = + workspace_manifest.data.get_mut("patch") + { + patch_section_table.set_implicit(true); + + for (_, item) in patch_section_table.iter_mut() { + if let toml_edit::Item::Table(patch_table) = item { + patch_table.set_implicit(true); + + for (key, item) in patch_table.iter_mut() { + let dep = Dependency::from_toml( + workspace.gctx(), + workspace.root(), + &workspace.root_manifest(), + workspace.unstable_features(), + key.get(), + item, + )?; + + // Generate a PackageIdSpec url for querying + let url = if let MaybeWorkspace::Other(source_id) = + dep.source_id(workspace.gctx())? + { + format!("{}#{}", source_id.url(), dep.name) + } else { + continue; + }; + + if PackageIdSpec::query_str(&url, resolve.unused_patches().iter().cloned()) + .is_ok() + { + *item = toml_edit::Item::None; + modified = true; + } + } + } + } + } + + if modified { + workspace_manifest.write()?; + } + + Ok(modified) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/report.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/report.rs new file mode 100644 index 000000000..75918699b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/report.rs @@ -0,0 +1,51 @@ +use crate::command_prelude::*; +use cargo::core::compiler::future_incompat::{OnDiskReports, REPORT_PREAMBLE}; +use cargo::drop_println; + +pub fn cli() -> Command { + subcommand("report") + .about("Generate and display various kinds of reports") + .after_help(color_print::cstr!( + "Run `cargo help report` for more detailed information.\n" + )) + .subcommand_required(true) + .arg_required_else_help(true) + .subcommand( + subcommand("future-incompatibilities") + .alias("future-incompat") + .about("Reports any crates which will eventually stop compiling") + .arg( + opt( + "id", + "identifier of the report generated by a Cargo command invocation", + ) + .value_name("id"), + ) + .arg_package("Package to display a report for"), + ) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + match args.subcommand() { + Some(("future-incompatibilities", args)) => report_future_incompatibilities(gctx, args), + Some((cmd, _)) => { + unreachable!("unexpected command {}", cmd) + } + None => { + unreachable!("unexpected command") + } + } +} + +fn report_future_incompatibilities(gctx: &GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + let reports = OnDiskReports::load(&ws)?; + let id = args + .value_of_u32("id")? + .unwrap_or_else(|| reports.last_id()); + let krate = args.get_one::("package").map(String::as_str); + let report = reports.get_report(id, krate)?; + drop_println!(gctx, "{}", REPORT_PREAMBLE); + drop(gctx.shell().print_ansi_stdout(report.as_bytes())); + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/run.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/run.rs new file mode 100644 index 000000000..aeec94381 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/run.rs @@ -0,0 +1,244 @@ +use std::ffi::OsStr; +use std::ffi::OsString; +use std::path::Path; + +use crate::command_prelude::*; +use crate::util::restricted_names::is_glob_pattern; +use cargo::core::Verbosity; +use cargo::core::Workspace; +use cargo::ops::{self, CompileFilter, Packages}; +use cargo::util::closest; +use cargo_util::ProcessError; +use itertools::Itertools as _; + +pub fn cli() -> Command { + subcommand("run") + // subcommand aliases are handled in aliased_command() + // .alias("r") + .about("Run a binary or example of the local package") + .arg( + Arg::new("args") + .value_name("ARGS") + .help("Arguments for the binary or example to run") + .value_parser(value_parser!(OsString)) + .num_args(0..) + .trailing_var_arg(true), + ) + .arg_message_format() + .arg_silent_suggestion() + .arg_package("Package with the target to run") + .arg_targets_bin_example( + "Name of the bin target to run", + "Name of the example target to run", + ) + .arg_features() + .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") + .arg_target_dir() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version() + .arg_unit_graph() + .arg_timings() + .after_help(color_print::cstr!( + "Run `cargo help run` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + + let mut compile_opts = + args.compile_options(gctx, CompileMode::Build, Some(&ws), ProfileChecking::Custom)?; + + // Disallow `spec` to be an glob pattern + if let Packages::Packages(opt_in) = &compile_opts.spec { + if let Some(pattern) = opt_in.iter().find(|s| is_glob_pattern(s)) { + return Err(anyhow::anyhow!( + "`cargo run` does not support glob pattern `{}` on package selection", + pattern, + ) + .into()); + } + } + + if !args.contains_id("example") && !args.contains_id("bin") { + let default_runs: Vec<_> = compile_opts + .spec + .get_packages(&ws)? + .iter() + .filter_map(|pkg| pkg.manifest().default_run()) + .collect(); + if let [bin] = &default_runs[..] { + compile_opts.filter = CompileFilter::single_bin(bin.to_string()); + } else { + // ops::run will take care of errors if len pkgs != 1. + compile_opts.filter = CompileFilter::Default { + // Force this to false because the code in ops::run is not + // able to pre-check features before compilation starts to + // enforce that only 1 binary is built. + required_features_filterable: false, + }; + } + }; + + ops::run(&ws, &compile_opts, &values_os(args, "args")).map_err(|err| to_run_error(gctx, err)) +} + +/// See also `util/toml/mod.rs`s `is_embedded` +pub fn is_manifest_command(arg: &str) -> bool { + let path = Path::new(arg); + 1 < path.components().count() || path.extension() == Some(OsStr::new("rs")) +} + +pub fn exec_manifest_command(gctx: &mut GlobalContext, cmd: &str, args: &[OsString]) -> CliResult { + let manifest_path = Path::new(cmd); + match (manifest_path.is_file(), gctx.cli_unstable().script) { + (true, true) => {} + (true, false) => { + return Err(anyhow::anyhow!("running the file `{cmd}` requires `-Zscript`").into()); + } + (false, true) => { + let possible_commands = crate::list_commands(gctx); + let is_dir = if manifest_path.is_dir() { + format!(": `{cmd}` is a directory") + } else { + "".to_owned() + }; + let suggested_command = if let Some(suggested_command) = possible_commands + .keys() + .filter(|c| cmd.starts_with(c.as_str())) + .max_by_key(|c| c.len()) + { + let actual_args = cmd.strip_prefix(suggested_command).unwrap(); + let args = if args.is_empty() { + "".to_owned() + } else { + format!( + " {}", + args.into_iter().map(|os| os.to_string_lossy()).join(" ") + ) + }; + format!("\nhelp: there is a command with a similar name: `{suggested_command} {actual_args}{args}`") + } else { + "".to_owned() + }; + let suggested_script = if let Some(suggested_script) = suggested_script(cmd) { + format!("\nhelp: there is a script with a similar name: `{suggested_script}`") + } else { + "".to_owned() + }; + return Err(anyhow::anyhow!( + "no such file or subcommand `{cmd}`{is_dir}{suggested_command}{suggested_script}" + ) + .into()); + } + (false, false) => { + // HACK: duplicating the above for minor tweaks but this will all go away on + // stabilization + let possible_commands = crate::list_commands(gctx); + let suggested_command = if let Some(suggested_command) = possible_commands + .keys() + .filter(|c| cmd.starts_with(c.as_str())) + .max_by_key(|c| c.len()) + { + let actual_args = cmd.strip_prefix(suggested_command).unwrap(); + let args = if args.is_empty() { + "".to_owned() + } else { + format!( + " {}", + args.into_iter().map(|os| os.to_string_lossy()).join(" ") + ) + }; + format!("\nhelp: there is a command with a similar name: `{suggested_command} {actual_args}{args}`") + } else { + "".to_owned() + }; + let suggested_script = if let Some(suggested_script) = suggested_script(cmd) { + format!("\nhelp: there is a script with a similar name: `{suggested_script}` (requires `-Zscript`)") + } else { + "".to_owned() + }; + return Err(anyhow::anyhow!( + "no such subcommand `{cmd}`{suggested_command}{suggested_script}" + ) + .into()); + } + } + + let manifest_path = root_manifest(Some(manifest_path), gctx)?; + + // Reload to cargo home. + gctx.reload_rooted_at(gctx.home().clone().into_path_unlocked())?; + + let mut ws = Workspace::new(&manifest_path, gctx)?; + if gctx.cli_unstable().avoid_dev_deps { + ws.set_require_optional_deps(false); + } + + let mut compile_opts = + cargo::ops::CompileOptions::new(gctx, cargo::core::compiler::CompileMode::Build)?; + compile_opts.spec = cargo::ops::Packages::Default; + + cargo::ops::run(&ws, &compile_opts, args).map_err(|err| to_run_error(gctx, err)) +} + +fn suggested_script(cmd: &str) -> Option { + let cmd_path = Path::new(cmd); + let mut suggestion = Path::new(".").to_owned(); + for cmd_part in cmd_path.components() { + let exact_match = suggestion.join(cmd_part); + suggestion = if exact_match.exists() { + exact_match + } else { + let possible: Vec<_> = std::fs::read_dir(suggestion) + .into_iter() + .flatten() + .filter_map(|e| e.ok()) + .map(|e| e.path()) + .filter(|p| p.to_str().is_some()) + .collect(); + if let Some(possible) = closest( + cmd_part.as_os_str().to_str().unwrap(), + possible.iter(), + |p| p.file_name().unwrap().to_str().unwrap(), + ) { + possible.to_owned() + } else { + return None; + } + }; + } + if suggestion.is_dir() { + None + } else { + suggestion.into_os_string().into_string().ok() + } +} + +fn to_run_error(gctx: &GlobalContext, err: anyhow::Error) -> CliError { + let proc_err = match err.downcast_ref::() { + Some(e) => e, + None => return CliError::new(err, 101), + }; + + // If we never actually spawned the process then that sounds pretty + // bad and we always want to forward that up. + let exit_code = match proc_err.code { + Some(exit) => exit, + None => return CliError::new(err, 101), + }; + + // If `-q` was passed then we suppress extra error information about + // a failed process, we assume the process itself printed out enough + // information about why it failed so we don't do so as well + let is_quiet = gctx.shell().verbosity() == Verbosity::Quiet; + if is_quiet { + CliError::code(exit_code) + } else { + CliError::new(err, exit_code) + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustc.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustc.rs new file mode 100644 index 000000000..ff660a335 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustc.rs @@ -0,0 +1,112 @@ +use crate::command_prelude::*; +use cargo::ops; +use cargo::util::interning::InternedString; + +const PRINT_ARG_NAME: &str = "print"; +const CRATE_TYPE_ARG_NAME: &str = "crate-type"; + +pub fn cli() -> Command { + subcommand("rustc") + .about("Compile a package, and pass extra options to the compiler") + .arg( + Arg::new("args") + .value_name("ARGS") + .num_args(0..) + .help("Extra rustc flags") + .trailing_var_arg(true), + ) + .arg( + opt( + PRINT_ARG_NAME, + "Output compiler information without compiling", + ) + .value_name("INFO"), + ) + .arg(multi_opt( + CRATE_TYPE_ARG_NAME, + "CRATE-TYPE", + "Comma separated list of types of crates for the compiler to emit", + )) + .arg_future_incompat_report() + .arg_message_format() + .arg_silent_suggestion() + .arg_package("Package to build") + .arg_targets_all( + "Build only this package's library", + "Build only the specified binary", + "Build all binaries", + "Build only the specified example", + "Build all examples", + "Build only the specified test target", + "Build all targets that have `test = true` set", + "Build only the specified bench target", + "Build all targets that have `bench = true` set", + "Build all targets", + ) + .arg_features() + .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") + .arg_target_dir() + .arg_unit_graph() + .arg_timings() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help rustc` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + // This is a legacy behavior that changes the behavior based on the profile. + // If we want to support this more formally, I think adding a --mode flag + // would be warranted. + let mode = match args.get_one::("profile").map(String::as_str) { + Some("test") => CompileMode::Test, + Some("bench") => CompileMode::Bench, + Some("check") => CompileMode::Check { test: false }, + _ => CompileMode::Build, + }; + let mut compile_opts = args.compile_options_for_single_package( + gctx, + mode, + Some(&ws), + ProfileChecking::LegacyRustc, + )?; + if compile_opts.build_config.requested_profile == "check" { + compile_opts.build_config.requested_profile = InternedString::new("dev"); + } + let target_args = values(args, "args"); + compile_opts.target_rustc_args = if target_args.is_empty() { + None + } else { + Some(target_args) + }; + if let Some(opt_value) = args.get_one::(PRINT_ARG_NAME) { + gctx.cli_unstable() + .fail_if_stable_opt(PRINT_ARG_NAME, 9357)?; + ops::print(&ws, &compile_opts, opt_value)?; + return Ok(()); + } + + let crate_types = args + .get_many::(CRATE_TYPE_ARG_NAME) + .into_iter() + .flatten() + .flat_map(|s| s.split(',')) + .filter(|s| !s.is_empty()) + .map(String::from) + .collect::>(); + + compile_opts.target_rustc_crate_types = if crate_types.is_empty() { + None + } else { + Some(crate_types) + }; + ops::compile(&ws, &compile_opts)?; + + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustdoc.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustdoc.rs new file mode 100644 index 000000000..be72d4b50 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/rustdoc.rs @@ -0,0 +1,89 @@ +use cargo::ops::{self, DocOptions, OutputFormat}; + +use crate::command_prelude::*; + +pub fn cli() -> Command { + subcommand("rustdoc") + .about("Build a package's documentation, using specified custom flags.") + .arg( + Arg::new("args") + .value_name("ARGS") + .help("Extra rustdoc flags") + .num_args(0..) + .trailing_var_arg(true), + ) + .arg(flag( + "open", + "Opens the docs in a browser after the operation", + )) + .arg_message_format() + .arg_silent_suggestion() + .arg_package("Package to document") + .arg_targets_all( + "Build only this package's library", + "Build only the specified binary", + "Build all binaries", + "Build only the specified example", + "Build all examples", + "Build only the specified test target", + "Build all targets that have `test = true` set", + "Build only the specified bench target", + "Build all targets that have `bench = true` set", + "Build all targets", + ) + .arg_features() + .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") + .arg_target_dir() + .arg( + opt("output-format", "The output type to write (unstable)") + .value_name("FMT") + .value_parser(OutputFormat::POSSIBLE_VALUES), + ) + .arg_unit_graph() + .arg_timings() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help rustdoc` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + let output_format = if let Some(output_format) = args._value_of("output-format") { + gctx.cli_unstable() + .fail_if_stable_opt("--output-format", 12103)?; + output_format.parse()? + } else { + OutputFormat::Html + }; + + let mut compile_opts = args.compile_options_for_single_package( + gctx, + CompileMode::Doc { + deps: false, + json: matches!(output_format, OutputFormat::Json), + }, + Some(&ws), + ProfileChecking::Custom, + )?; + let target_args = values(args, "args"); + + compile_opts.target_rustdoc_args = if target_args.is_empty() { + None + } else { + Some(target_args) + }; + + let doc_opts = DocOptions { + open_result: args.flag("open"), + output_format, + compile_opts, + }; + ops::doc(&ws, &doc_opts)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/search.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/search.rs new file mode 100644 index 000000000..f51f59d2d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/search.rs @@ -0,0 +1,38 @@ +use crate::command_prelude::*; + +use std::cmp::min; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("search") + .about("Search packages in the registry. Default registry is crates.io") + .arg(Arg::new("query").value_name("QUERY").num_args(0..)) + .arg( + opt( + "limit", + "Limit the number of results (default: 10, max: 100)", + ) + .value_name("LIMIT"), + ) + .arg_index("Registry index URL to search packages in") + .arg_registry("Registry to search packages in") + .arg_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help search` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let reg_or_index = args.registry_or_index(gctx)?; + let limit = args.value_of_u32("limit")?; + let limit = min(100, limit.unwrap_or(10)); + let query: Vec<&str> = args + .get_many::("query") + .unwrap_or_default() + .map(String::as_str) + .collect(); + let query: String = query.join("+"); + ops::search(&query, gctx, reg_or_index, limit)?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/test.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/test.rs new file mode 100644 index 000000000..45e77e4da --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/test.rs @@ -0,0 +1,115 @@ +use crate::command_prelude::*; +use cargo::ops; + +pub fn cli() -> Command { + subcommand("test") + // Subcommand aliases are handled in `aliased_command()`. + // .alias("t") + .about("Execute all unit and integration tests and build examples of a local package") + .arg( + Arg::new("TESTNAME") + .action(ArgAction::Set) + .help("If specified, only run tests containing this string in their names"), + ) + .arg( + Arg::new("args") + .value_name("ARGS") + .help("Arguments for the test binary") + .num_args(0..) + .last(true), + ) + .arg(flag("no-run", "Compile, but don't run tests")) + .arg(flag("no-fail-fast", "Run all tests regardless of failure")) + .arg_future_incompat_report() + .arg_message_format() + .arg( + flag( + "quiet", + "Display one character per test instead of one line", + ) + .short('q'), + ) + .arg_package_spec( + "Package to run tests for", + "Test all packages in the workspace", + "Exclude packages from the test", + ) + .arg_targets_all( + "Test only this package's library", + "Test only the specified binary", + "Test all binaries", + "Test only the specified example", + "Test all examples", + "Test only the specified test target", + "Test all targets that have `test = true` set", + "Test only the specified bench target", + "Test all targets that have `bench = true` set", + "Test all targets (does not include doctests)", + ) + .arg( + flag("doc", "Test only this library's documentation") + .help_heading(heading::TARGET_SELECTION), + ) + .arg_features() + .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") + .arg_target_dir() + .arg_unit_graph() + .arg_timings() + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version() + .after_help(color_print::cstr!( + "Run `cargo help test` for more detailed information.\n\ + Run `cargo test -- --help` for test binary options.\n", + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let ws = args.workspace(gctx)?; + + let mut compile_opts = + args.compile_options(gctx, CompileMode::Test, Some(&ws), ProfileChecking::Custom)?; + + compile_opts.build_config.requested_profile = + 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. + let test_name = args.get_one::("TESTNAME"); + let test_args = args.get_one::("TESTNAME").into_iter(); + let test_args = test_args.chain(args.get_many::("args").unwrap_or_default()); + let test_args = test_args.map(String::as_str).collect::>(); + + let no_run = args.flag("no-run"); + let doc = args.flag("doc"); + if doc { + if compile_opts.filter.is_specific() { + return Err( + anyhow::format_err!("Can't mix --doc with other target selecting options").into(), + ); + } + if no_run { + return Err(anyhow::format_err!("Can't skip running doc tests with --no-run").into()); + } + compile_opts.build_config.mode = CompileMode::Doctest; + compile_opts.filter = ops::CompileFilter::lib_only(); + } else if test_name.is_some() && !compile_opts.filter.is_specific() { + // If arg `TESTNAME` is provided, assumed that the user knows what + // exactly they wants to test, so we use `all_test_targets` to + // avoid compiling unnecessary targets such as examples, which are + // included by the logic of default target filter. + compile_opts.filter = ops::CompileFilter::all_test_targets(); + } + + let ops = ops::TestOptions { + no_run, + no_fail_fast: args.flag("no-fail-fast"), + compile_opts, + }; + + ops::run_tests(&ws, &ops, &test_args) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/tree.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/tree.rs new file mode 100644 index 000000000..98b21db6c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/tree.rs @@ -0,0 +1,338 @@ +use crate::cli; +use crate::command_prelude::*; +use anyhow::{bail, format_err}; +use cargo::core::dependency::DepKind; +use cargo::ops::tree::{self, DisplayDepth, EdgeKind}; +use cargo::ops::Packages; +use cargo::util::print_available_packages; +use cargo::util::CargoResult; +use std::collections::HashSet; +use std::str::FromStr; + +pub fn cli() -> Command { + subcommand("tree") + .about("Display a tree visualization of a dependency graph") + .arg( + flag("all", "Deprecated, use --no-dedupe instead") + .short('a') + .hide(true), + ) + .arg_silent_suggestion() + .arg(flag("no-dev-dependencies", "Deprecated, use -e=no-dev instead").hide(true)) + .arg( + multi_opt( + "edges", + "KINDS", + "The kinds of dependencies to display \ + (features, normal, build, dev, all, \ + no-normal, no-build, no-dev, no-proc-macro)", + ) + .short('e'), + ) + .arg( + optional_multi_opt( + "invert", + "SPEC", + "Invert the tree direction and focus on the given package", + ) + .short('i'), + ) + .arg(multi_opt( + "prune", + "SPEC", + "Prune the given package from the display of the dependency tree", + )) + .arg(opt("depth", "Maximum display depth of the dependency tree").value_name("DEPTH")) + .arg(flag("no-indent", "Deprecated, use --prefix=none instead").hide(true)) + .arg(flag("prefix-depth", "Deprecated, use --prefix=depth instead").hide(true)) + .arg( + opt( + "prefix", + "Change the prefix (indentation) of how each entry is displayed", + ) + .value_name("PREFIX") + .value_parser(["depth", "indent", "none"]) + .default_value("indent"), + ) + .arg(flag( + "no-dedupe", + "Do not de-duplicate (repeats all shared dependencies)", + )) + .arg( + flag( + "duplicates", + "Show only dependencies which come in multiple versions (implies -i)", + ) + .short('d') + .alias("duplicate"), + ) + .arg( + opt("charset", "Character set to use in output") + .value_name("CHARSET") + .value_parser(["utf8", "ascii"]), + ) + .arg( + opt("format", "Format string used for printing dependencies") + .value_name("FORMAT") + .short('f') + .default_value("{p}"), + ) + .arg( + // Backwards compatibility with old cargo-tree. + flag("version", "Print version info and exit") + .short('V') + .hide(true), + ) + .arg_package_spec_no_all( + "Package to be used as the root of the tree", + "Display the tree for all packages in the workspace", + "Exclude specific workspace members", + ) + .arg_features() + .arg(flag("all-targets", "Deprecated, use --target=all instead").hide(true)) + .arg_target_triple( + "Filter dependencies matching the given target-triple (default host platform). \ + Pass `all` to include all targets.", + ) + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `cargo help tree` for more detailed information.\n" + )) +} + +#[derive(Copy, Clone)] +pub enum Charset { + Utf8, + Ascii, +} + +impl FromStr for Charset { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "utf8" => Ok(Charset::Utf8), + "ascii" => Ok(Charset::Ascii), + _ => Err("invalid charset"), + } + } +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + if args.flag("version") { + let verbose = args.verbose() > 0; + let version = cli::get_version_string(verbose); + cargo::drop_print!(gctx, "{}", version); + return Ok(()); + } + let prefix = if args.flag("no-indent") { + gctx.shell() + .warn("the --no-indent flag has been changed to --prefix=none")?; + "none" + } else if args.flag("prefix-depth") { + gctx.shell() + .warn("the --prefix-depth flag has been changed to --prefix=depth")?; + "depth" + } else { + args.get_one::("prefix").unwrap().as_str() + }; + let prefix = tree::Prefix::from_str(prefix).map_err(|e| anyhow::anyhow!("{}", e))?; + + let no_dedupe = args.flag("no-dedupe") || args.flag("all"); + if args.flag("all") { + gctx.shell().warn( + "The `cargo tree` --all flag has been changed to --no-dedupe, \ + and may be removed in a future version.\n\ + If you are looking to display all workspace members, use the --workspace flag.", + )?; + } + + let targets = if args.flag("all-targets") { + gctx.shell() + .warn("the --all-targets flag has been changed to --target=all")?; + vec!["all".to_string()] + } else { + args.targets()? + }; + let target = tree::Target::from_cli(targets); + + let (edge_kinds, no_proc_macro) = parse_edge_kinds(gctx, args)?; + let graph_features = edge_kinds.contains(&EdgeKind::Feature); + + let pkgs_to_prune = args._values_of("prune"); + + let display_depth = args + ._value_of("depth") + .map(|s| s.parse::()) + .transpose()? + .unwrap_or(DisplayDepth::MaxDisplayDepth(u32::MAX)); + + let packages = args.packages_from_flags()?; + let mut invert = args + .get_many::("invert") + .map_or_else(|| Vec::new(), |is| is.map(|s| s.to_string()).collect()); + if args.is_present_with_zero_values("invert") { + match &packages { + Packages::Packages(ps) => { + // Backwards compatibility with old syntax of `cargo tree -i -p foo`. + invert.extend(ps.clone()); + } + _ => { + return Err(format_err!( + "The `-i` flag requires a package name.\n\ +\n\ +The `-i` flag is used to inspect the reverse dependencies of a specific\n\ +package. It will invert the tree and display the packages that depend on the\n\ +given package.\n\ +\n\ +Note that in a workspace, by default it will only display the package's\n\ +reverse dependencies inside the tree of the workspace member in the current\n\ +directory. The --workspace flag can be used to extend it so that it will show\n\ +the package's reverse dependencies across the entire workspace. The -p flag\n\ +can be used to display the package's reverse dependencies only with the\n\ +subtree of the package given to -p.\n\ +" + ) + .into()); + } + } + } + + let ws = args.workspace(gctx)?; + + if args.is_present_with_zero_values("package") { + print_available_packages(&ws)?; + } + + let charset = args.get_one::("charset"); + if let Some(charset) = charset + .map(|c| Charset::from_str(c)) + .transpose() + .map_err(|e| anyhow::anyhow!("{}", e))? + { + match charset { + Charset::Utf8 => gctx.shell().set_unicode(true)?, + Charset::Ascii => gctx.shell().set_unicode(false)?, + } + } + let opts = tree::TreeOptions { + cli_features: args.cli_features()?, + packages, + target, + edge_kinds, + invert, + pkgs_to_prune, + prefix, + no_dedupe, + duplicates: args.flag("duplicates"), + format: args.get_one::("format").cloned().unwrap(), + graph_features, + display_depth, + no_proc_macro, + }; + + if opts.graph_features && opts.duplicates { + return Err(format_err!("the `-e features` flag does not support `--duplicates`").into()); + } + + tree::build_and_print(&ws, &opts)?; + Ok(()) +} + +/// Parses `--edges` option. +/// +/// Returns a tuple of `EdgeKind` map and `no_proc_marco` flag. +fn parse_edge_kinds( + gctx: &GlobalContext, + args: &ArgMatches, +) -> CargoResult<(HashSet, bool)> { + let (kinds, no_proc_macro) = { + let mut no_proc_macro = false; + let mut kinds = args.get_many::("edges").map_or_else( + || Vec::new(), + |es| { + es.flat_map(|e| e.split(',')) + .filter(|e| { + no_proc_macro = *e == "no-proc-macro"; + !no_proc_macro + }) + .collect() + }, + ); + + if args.flag("no-dev-dependencies") { + gctx.shell() + .warn("the --no-dev-dependencies flag has changed to -e=no-dev")?; + kinds.push("no-dev"); + } + + if kinds.is_empty() { + kinds.extend(&["normal", "build", "dev"]); + } + + (kinds, no_proc_macro) + }; + + let mut result = HashSet::new(); + let insert_defaults = |result: &mut HashSet| { + result.insert(EdgeKind::Dep(DepKind::Normal)); + result.insert(EdgeKind::Dep(DepKind::Build)); + result.insert(EdgeKind::Dep(DepKind::Development)); + }; + let unknown = |k| { + bail!( + "unknown edge kind `{}`, valid values are \ + \"normal\", \"build\", \"dev\", \ + \"no-normal\", \"no-build\", \"no-dev\", \"no-proc-macro\", \ + \"features\", or \"all\"", + k + ) + }; + if kinds.iter().any(|k| k.starts_with("no-")) { + insert_defaults(&mut result); + for kind in &kinds { + match *kind { + "no-normal" => result.remove(&EdgeKind::Dep(DepKind::Normal)), + "no-build" => result.remove(&EdgeKind::Dep(DepKind::Build)), + "no-dev" => result.remove(&EdgeKind::Dep(DepKind::Development)), + "features" => result.insert(EdgeKind::Feature), + "normal" | "build" | "dev" | "all" => { + bail!( + "`{}` dependency kind cannot be mixed with \ + \"no-normal\", \"no-build\", or \"no-dev\" \ + dependency kinds", + kind + ) + } + k => return unknown(k), + }; + } + return Ok((result, no_proc_macro)); + } + for kind in &kinds { + match *kind { + "all" => { + insert_defaults(&mut result); + result.insert(EdgeKind::Feature); + } + "features" => { + result.insert(EdgeKind::Feature); + } + "normal" => { + result.insert(EdgeKind::Dep(DepKind::Normal)); + } + "build" => { + result.insert(EdgeKind::Dep(DepKind::Build)); + } + "dev" => { + result.insert(EdgeKind::Dep(DepKind::Development)); + } + k => return unknown(k), + } + } + if kinds.len() == 1 && kinds[0] == "features" { + insert_defaults(&mut result); + } + Ok((result, no_proc_macro)) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/uninstall.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/uninstall.rs new file mode 100644 index 000000000..d50996d9a --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/uninstall.rs @@ -0,0 +1,68 @@ +use crate::command_prelude::*; + +use cargo::ops; + +pub fn cli() -> Command { + subcommand("uninstall") + .about("Remove a Rust binary") + .arg( + Arg::new("spec") + .value_name("SPEC") + .num_args(0..) + .add::(clap_complete::ArgValueCandidates::new( + || get_installed_crates(), + )), + ) + .arg(opt("root", "Directory to uninstall packages from").value_name("DIR")) + .arg_silent_suggestion() + .arg_package_spec_simple("Package to uninstall") + .arg( + multi_opt("bin", "NAME", "Only uninstall the binary NAME") + .help_heading(heading::TARGET_SELECTION), + ) + .after_help(color_print::cstr!( + "Run `cargo help uninstall` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let root = args.get_one::("root").map(String::as_str); + + if args.is_present_with_zero_values("package") { + return Err(anyhow::anyhow!( + "\"--package \" requires a SPEC format value.\n\ + Run `cargo help pkgid` for more information about SPEC format." + ) + .into()); + } + + let specs = args + .get_many::("spec") + .unwrap_or_else(|| args.get_many::("package").unwrap_or_default()) + .map(String::as_str) + .collect(); + ops::uninstall(root, specs, &values(args, "bin"), gctx)?; + Ok(()) +} + +fn get_installed_crates() -> Vec { + get_installed_crates_().unwrap_or_default() +} + +fn get_installed_crates_() -> Option> { + let mut candidates = Vec::new(); + + let gctx = GlobalContext::default().ok()?; + + let root = ops::resolve_root(None, &gctx).ok()?; + + let tracker = ops::InstallTracker::load(&gctx, &root).ok()?; + + for (_, v) in tracker.all_installed_bins() { + for bin in v { + candidates.push(clap_complete::CompletionCandidate::new(bin)); + } + } + + Some(candidates) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/update.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/update.rs new file mode 100644 index 000000000..3b89d037d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/update.rs @@ -0,0 +1,113 @@ +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") + .add(clap_complete::ArgValueCandidates::new( + get_pkg_id_spec_candidates, + ))]) + .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( + "recursive", + "Force updating all dependencies of [SPEC]... as well", + ) + .alias("aggressive") + .conflicts_with("precise"), + ) + .arg( + opt("precise", "Update [SPEC] to exactly PRECISE") + .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") + .short('w') + .help_heading(heading::PACKAGE_SELECTION), + ) + .arg_manifest_path() + .arg_lockfile_path() + .arg_ignore_rust_version_with_help("Ignore `rust-version` specification in packages") + .after_help(color_print::cstr!( + "Run `cargo help update` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let mut ws = args.workspace(gctx)?; + + if args.is_present_with_zero_values("package") { + 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 { + recursive: args.flag("recursive"), + precise: args.get_one::("precise").map(String::as_str), + to_update, + dry_run: args.dry_run(), + workspace: args.flag("workspace"), + gctx, + }; + + 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/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/vendor.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/vendor.rs new file mode 100644 index 000000000..96b306767 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/vendor.rs @@ -0,0 +1,86 @@ +use crate::command_prelude::*; +use cargo::ops; +use std::path::PathBuf; + +pub fn cli() -> Command { + subcommand("vendor") + .about("Vendor all dependencies for a project locally") + .arg( + Arg::new("path") + .action(ArgAction::Set) + .value_parser(clap::value_parser!(PathBuf)) + .help("Where to vendor crates (`vendor` by default)"), + ) + .arg(flag( + "no-delete", + "Don't delete older crates in the vendor directory", + )) + .arg( + Arg::new("tomls") + .short('s') + .long("sync") + .help("Additional `Cargo.toml` to sync and vendor") + .value_name("TOML") + .value_parser(clap::value_parser!(PathBuf)) + .action(clap::ArgAction::Append), + ) + .arg(flag( + "respect-source-config", + "Respect `[source]` config in `.cargo/config`", + )) + .arg(flag( + "versioned-dirs", + "Always include version in subdir name", + )) + .arg(unsupported("no-merge-sources")) + .arg(unsupported("relative-path")) + .arg(unsupported("only-git-deps")) + .arg(unsupported("disallow-duplicates")) + .arg_manifest_path() + .arg_lockfile_path() + .after_help(color_print::cstr!( + "Run `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 "); + + flag(name, "").value_parser(value_parser).hide(true) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + // We're doing the vendoring operation ourselves, so we don't actually want + // to respect any of the `source` configuration in Cargo itself. That's + // intended for other consumers of Cargo, but we want to go straight to the + // source, e.g. crates.io, to fetch crates. + if !args.flag("respect-source-config") { + gctx.values_mut()?.remove("source"); + } + + let ws = args.workspace(gctx)?; + let path = args + .get_one::("path") + .cloned() + .unwrap_or_else(|| PathBuf::from("vendor")); + ops::vendor( + &ws, + &ops::VendorOptions { + no_delete: args.flag("no-delete"), + destination: &path, + versioned_dirs: args.flag("versioned-dirs"), + extra: args + .get_many::("tomls") + .unwrap_or_default() + .cloned() + .collect(), + }, + )?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/verify_project.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/verify_project.rs new file mode 100644 index 000000000..12564abf2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/verify_project.rs @@ -0,0 +1,31 @@ +//! Deprecated. + +use crate::command_prelude::*; + +use std::collections::HashMap; +use std::process; + +pub fn cli() -> Command { + subcommand("verify-project") + .hide(true) + .about( + "\ +DEPRECATED: Check correctness of crate manifest. + +See https://github.com/rust-lang/cargo/issues/14679.", + ) + .arg_silent_suggestion() + .arg_manifest_path() +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + if let Err(e) = args.workspace(gctx) { + gctx.shell() + .print_json(&HashMap::from([("invalid", e.to_string())]))?; + process::exit(1) + } + + gctx.shell() + .print_json(&HashMap::from([("success", "true")]))?; + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/version.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/version.rs new file mode 100644 index 000000000..78d3c658f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/version.rs @@ -0,0 +1,18 @@ +use crate::cli; +use crate::command_prelude::*; + +pub fn cli() -> Command { + subcommand("version") + .about("Show version information") + .arg_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help version` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let verbose = args.verbose() > 0; + let version = cli::get_version_string(verbose); + cargo::drop_print!(gctx, "{}", version); + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/yank.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/yank.rs new file mode 100644 index 000000000..5401b32de --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/commands/yank.rs @@ -0,0 +1,64 @@ +use crate::command_prelude::*; + +use cargo::ops; +use cargo_credential::Secret; + +pub fn cli() -> Command { + subcommand("yank") + .about("Remove a pushed crate from the index") + .arg(Arg::new("crate").value_name("CRATE").action(ArgAction::Set)) + .arg( + opt("version", "The version to yank or un-yank") + .alias("vers") + .value_name("VERSION"), + ) + .arg(flag( + "undo", + "Undo a yank, putting a version back into the index", + )) + .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_silent_suggestion() + .after_help(color_print::cstr!( + "Run `cargo help yank` for more detailed information.\n" + )) +} + +pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { + let (krate, version) = resolve_crate( + args.get_one::("crate").map(String::as_str), + args.get_one::("version").map(String::as_str), + )?; + if version.is_none() { + return Err(anyhow::format_err!("`--version` is required").into()); + } + + ops::yank( + gctx, + krate.map(|s| s.to_string()), + version.map(|s| s.to_string()), + args.get_one::("token").cloned().map(Secret::from), + args.registry_or_index(gctx)?, + args.flag("undo"), + )?; + Ok(()) +} + +fn resolve_crate<'k>( + mut krate: Option<&'k str>, + mut version: Option<&'k str>, +) -> crate::CargoResult<(Option<&'k str>, Option<&'k str>)> { + if let Some((k, v)) = krate.and_then(|k| k.split_once('@')) { + if version.is_some() { + anyhow::bail!("cannot specify both `@{v}` and `--version`"); + } + if k.is_empty() { + // by convention, arguments starting with `@` are response files + anyhow::bail!("missing crate name for `@{v}`"); + } + krate = Some(k); + version = Some(v); + } + Ok((krate, version)) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/main.rs b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/main.rs new file mode 100644 index 000000000..f103dffa4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/bin/cargo/main.rs @@ -0,0 +1,441 @@ +#![allow(clippy::self_named_module_files)] // false positive in `commands/build.rs` + +use cargo::core::features; +use cargo::core::shell::Shell; +use cargo::util::network::http::http_handle; +use cargo::util::network::http::needs_custom_http_transport; +use cargo::util::{self, closest_msg, command_prelude, CargoResult}; +use cargo_util::{ProcessBuilder, ProcessError}; +use cargo_util_schemas::manifest::StringOrVec; +use std::collections::BTreeMap; +use std::env; +use std::ffi::OsStr; +use std::fs; +use std::path::{Path, PathBuf}; + +mod cli; +mod commands; + +use crate::command_prelude::*; + +fn main() { + let _guard = setup_logger(); + + let mut gctx = match GlobalContext::default() { + Ok(gctx) => gctx, + Err(e) => { + let mut shell = Shell::new(); + cargo::exit_with_error(e.into(), &mut shell) + } + }; + + let nightly_features_allowed = matches!(&*features::channel(), "nightly" | "dev"); + if nightly_features_allowed { + let _span = tracing::span!(tracing::Level::TRACE, "completions").entered(); + let args = std::env::args_os(); + let current_dir = std::env::current_dir().ok(); + let completer = clap_complete::CompleteEnv::with_factory(|| { + let mut gctx = GlobalContext::default().expect("already loaded without errors"); + cli::cli(&mut gctx) + }) + .var("CARGO_COMPLETE"); + if completer + .try_complete(args, current_dir.as_deref()) + .unwrap_or_else(|e| { + let mut shell = Shell::new(); + cargo::exit_with_error(e.into(), &mut shell) + }) + { + return; + } + } + + let result = if let Some(lock_addr) = cargo::ops::fix_get_proxy_lock_addr() { + cargo::ops::fix_exec_rustc(&gctx, &lock_addr).map_err(|e| CliError::from(e)) + } else { + let _token = cargo::util::job::setup(); + cli::main(&mut gctx) + }; + + match result { + Err(e) => cargo::exit_with_error(e, &mut *gctx.shell()), + Ok(()) => {} + } +} + +fn setup_logger() -> Option { + use tracing_subscriber::prelude::*; + + let env = tracing_subscriber::EnvFilter::from_env("CARGO_LOG"); + let fmt_layer = tracing_subscriber::fmt::layer() + .with_timer(tracing_subscriber::fmt::time::Uptime::default()) + .with_ansi(std::io::IsTerminal::is_terminal(&std::io::stderr())) + .with_writer(std::io::stderr) + .with_filter(env); + + let (profile_layer, profile_guard) = chrome_layer(); + + let registry = tracing_subscriber::registry() + .with(fmt_layer) + .with(profile_layer); + registry.init(); + tracing::trace!(start = humantime::format_rfc3339(std::time::SystemTime::now()).to_string()); + profile_guard +} + +#[cfg(target_has_atomic = "64")] +type ChromeFlushGuard = tracing_chrome::FlushGuard; +#[cfg(target_has_atomic = "64")] +fn chrome_layer() -> ( + Option>, + Option, +) +where + S: tracing::Subscriber + + for<'span> tracing_subscriber::registry::LookupSpan<'span> + + Send + + Sync, +{ + #![allow(clippy::disallowed_methods)] + + if env_to_bool(std::env::var_os("CARGO_LOG_PROFILE").as_deref()) { + let capture_args = + env_to_bool(std::env::var_os("CARGO_LOG_PROFILE_CAPTURE_ARGS").as_deref()); + let (layer, guard) = tracing_chrome::ChromeLayerBuilder::new() + .include_args(capture_args) + .build(); + (Some(layer), Some(guard)) + } else { + (None, None) + } +} + +#[cfg(not(target_has_atomic = "64"))] +type ChromeFlushGuard = (); +#[cfg(not(target_has_atomic = "64"))] +fn chrome_layer() -> ( + Option, + Option, +) { + (None, None) +} + +#[cfg(target_has_atomic = "64")] +fn env_to_bool(os: Option<&OsStr>) -> bool { + match os.and_then(|os| os.to_str()) { + Some("1") | Some("true") => true, + _ => false, + } +} + +/// Table for defining the aliases which come builtin in `Cargo`. +/// The contents are structured as: `(alias, aliased_command, description)`. +const BUILTIN_ALIASES: [(&str, &str, &str); 6] = [ + ("b", "build", "alias: build"), + ("c", "check", "alias: check"), + ("d", "doc", "alias: doc"), + ("r", "run", "alias: run"), + ("t", "test", "alias: test"), + ("rm", "remove", "alias: remove"), +]; + +/// Function which contains the list of all of the builtin aliases and it's +/// corresponding execs represented as &str. +fn builtin_aliases_execs(cmd: &str) -> Option<&(&str, &str, &str)> { + BUILTIN_ALIASES.iter().find(|alias| alias.0 == cmd) +} + +/// Resolve the aliased command from the [`GlobalContext`] with a given command string. +/// +/// The search fallback chain is: +/// +/// 1. Get the aliased command as a string. +/// 2. If an `Err` occurs (missing key, type mismatch, or any possible error), +/// try to get it as an array again. +/// 3. If still cannot find any, finds one insides [`BUILTIN_ALIASES`]. +fn aliased_command(gctx: &GlobalContext, command: &str) -> CargoResult>> { + let alias_name = format!("alias.{}", command); + let user_alias = match gctx.get_string(&alias_name) { + Ok(Some(record)) => Some( + record + .val + .split_whitespace() + .map(|s| s.to_string()) + .collect(), + ), + Ok(None) => None, + Err(_) => gctx.get::>>(&alias_name)?, + }; + + let result = user_alias.or_else(|| { + builtin_aliases_execs(command).map(|command_str| vec![command_str.1.to_string()]) + }); + if result + .as_ref() + .map(|alias| alias.is_empty()) + .unwrap_or_default() + { + anyhow::bail!("subcommand is required, but `{alias_name}` is empty"); + } + Ok(result) +} + +/// List all runnable commands +fn list_commands(gctx: &GlobalContext) -> BTreeMap { + let mut commands = third_party_subcommands(gctx); + + for cmd in commands::builtin() { + commands.insert( + cmd.get_name().to_string(), + CommandInfo::BuiltIn { + about: cmd.get_about().map(|s| s.to_string()), + }, + ); + } + + // Add the builtin_aliases and them descriptions to the + // `commands` `BTreeMap`. + for command in &BUILTIN_ALIASES { + commands.insert( + command.0.to_string(), + CommandInfo::BuiltIn { + about: Some(command.2.to_string()), + }, + ); + } + + // Add the user-defined aliases + let alias_commands = user_defined_aliases(gctx); + commands.extend(alias_commands); + + // `help` is special, so it needs to be inserted separately. + commands.insert( + "help".to_string(), + CommandInfo::BuiltIn { + about: Some("Displays help for a cargo subcommand".to_string()), + }, + ); + + commands +} + +fn third_party_subcommands(gctx: &GlobalContext) -> BTreeMap { + let prefix = "cargo-"; + let suffix = env::consts::EXE_SUFFIX; + let mut commands = BTreeMap::new(); + for dir in search_directories(gctx) { + let entries = match fs::read_dir(dir) { + Ok(entries) => entries, + _ => continue, + }; + for entry in entries.filter_map(|e| e.ok()) { + let path = entry.path(); + let Some(filename) = path.file_name().and_then(|s| s.to_str()) else { + continue; + }; + let Some(name) = filename + .strip_prefix(prefix) + .and_then(|s| s.strip_suffix(suffix)) + else { + continue; + }; + if is_executable(entry.path()) { + commands.insert( + name.to_string(), + CommandInfo::External { path: path.clone() }, + ); + } + } + } + commands +} + +fn user_defined_aliases(gctx: &GlobalContext) -> BTreeMap { + let mut commands = BTreeMap::new(); + if let Ok(aliases) = gctx.get::>("alias") { + for (name, target) in aliases.iter() { + commands.insert( + name.to_string(), + CommandInfo::Alias { + target: target.clone(), + }, + ); + } + } + commands +} + +fn find_external_subcommand(gctx: &GlobalContext, cmd: &str) -> Option { + let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX); + search_directories(gctx) + .iter() + .map(|dir| dir.join(&command_exe)) + .find(|file| is_executable(file)) +} + +fn execute_external_subcommand(gctx: &GlobalContext, cmd: &str, args: &[&OsStr]) -> CliResult { + let path = find_external_subcommand(gctx, cmd); + let command = match path { + Some(command) => command, + None => { + let script_suggestion = + if gctx.cli_unstable().script && std::path::Path::new(cmd).is_file() { + let sep = std::path::MAIN_SEPARATOR; + format!( + "\nhelp: To run the file `{cmd}`, provide a relative path like `.{sep}{cmd}`" + ) + } else { + "".to_owned() + }; + let err = if cmd.starts_with('+') { + anyhow::format_err!( + "no such command: `{cmd}`\n\n\ + help: invoke `cargo` through `rustup` to handle `+toolchain` directives{script_suggestion}", + ) + } else { + let suggestions = list_commands(gctx); + let did_you_mean = closest_msg(cmd, suggestions.keys(), |c| c, "command"); + + anyhow::format_err!( + "no such command: `{cmd}`{did_you_mean}\n\n\ + help: view all installed commands with `cargo --list`\n\ + help: find a package to install `{cmd}` with `cargo search cargo-{cmd}`{script_suggestion}", + ) + }; + + return Err(CliError::new(err, 101)); + } + }; + execute_subcommand(gctx, Some(&command), args) +} + +fn execute_internal_subcommand(gctx: &GlobalContext, args: &[&OsStr]) -> CliResult { + execute_subcommand(gctx, None, args) +} + +// This function is used to execute a subcommand. It is used to execute both +// internal and external subcommands. +// If `cmd_path` is `None`, then the subcommand is an internal subcommand. +fn execute_subcommand( + gctx: &GlobalContext, + cmd_path: Option<&PathBuf>, + args: &[&OsStr], +) -> CliResult { + let cargo_exe = gctx.cargo_exe()?; + let mut cmd = match cmd_path { + Some(cmd_path) => ProcessBuilder::new(cmd_path), + None => ProcessBuilder::new(&cargo_exe), + }; + cmd.env(cargo::CARGO_ENV, cargo_exe).args(args); + if let Some(client) = gctx.jobserver_from_env() { + cmd.inherit_jobserver(client); + } + let err = match cmd.exec_replace() { + Ok(()) => return Ok(()), + Err(e) => e, + }; + + if let Some(perr) = err.downcast_ref::() { + if let Some(code) = perr.code { + return Err(CliError::code(code)); + } + } + Err(CliError::new(err, 101)) +} + +#[cfg(unix)] +fn is_executable>(path: P) -> bool { + use std::os::unix::prelude::*; + fs::metadata(path) + .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0) + .unwrap_or(false) +} +#[cfg(windows)] +fn is_executable>(path: P) -> bool { + path.as_ref().is_file() +} + +fn search_directories(gctx: &GlobalContext) -> Vec { + let mut path_dirs = if let Some(val) = gctx.get_env_os("PATH") { + env::split_paths(&val).collect() + } else { + vec![] + }; + + let home_bin = gctx.home().clone().into_path_unlocked().join("bin"); + + // If any of that PATH elements contains `home_bin`, do not + // add it again. This is so that the users can control priority + // of it using PATH, while preserving the historical + // behavior of preferring it over system global directories even + // when not in PATH at all. + // See https://github.com/rust-lang/cargo/issues/11020 for details. + // + // Note: `p == home_bin` will ignore trailing slash, but we don't + // `canonicalize` the paths. + if !path_dirs.iter().any(|p| p == &home_bin) { + path_dirs.insert(0, home_bin); + }; + + path_dirs +} + +/// Initialize libgit2. +#[tracing::instrument(skip_all)] +fn init_git(gctx: &GlobalContext) { + // Disabling the owner validation in git can, in theory, lead to code execution + // vulnerabilities. However, libgit2 does not launch executables, which is the foundation of + // the original security issue. Meanwhile, issues with refusing to load git repos in + // `CARGO_HOME` for example will likely be very frustrating for users. So, we disable the + // validation. + // + // For further discussion of Cargo's current interactions with git, see + // + // https://github.com/rust-lang/rfcs/pull/3279 + // + // and in particular the subsection on "Git support". + // + // Note that we only disable this when Cargo is run as a binary. If Cargo is used as a library, + // this code won't be invoked. Instead, developers will need to explicitly disable the + // validation in their code. This is inconvenient, but won't accidentally open consuming + // applications up to security issues if they use git2 to open repositories elsewhere in their + // code. + unsafe { + git2::opts::set_verify_owner_validation(false) + .expect("set_verify_owner_validation should never fail"); + } + + init_git_transports(gctx); +} + +/// Configure libgit2 to use libcurl if necessary. +/// +/// If the user has a non-default network configuration, then libgit2 will be +/// configured to use libcurl instead of the built-in networking support so +/// that those configuration settings can be used. +#[tracing::instrument(skip_all)] +fn init_git_transports(gctx: &GlobalContext) { + match needs_custom_http_transport(gctx) { + Ok(true) => {} + _ => return, + } + + let handle = match http_handle(gctx) { + Ok(handle) => handle, + Err(..) => return, + }; + + // The unsafety of the registration function derives from two aspects: + // + // 1. This call must be synchronized with all other registration calls as + // well as construction of new transports. + // 2. The argument is leaked. + // + // We're clear on point (1) because this is only called at the start of this + // binary (we know what the state of the world looks like) and we're mostly + // clear on point (2) because we'd only free it after everything is done + // anyway + unsafe { + git2_curl::register(handle); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/artifact.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/artifact.rs new file mode 100644 index 000000000..eb31cef0f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/artifact.rs @@ -0,0 +1,122 @@ +//! Generate artifact information from unit dependencies for configuring the compiler environment. + +use crate::core::compiler::unit_graph::UnitDep; +use crate::core::compiler::{BuildRunner, CrateType, FileFlavor, Unit}; +use crate::core::dependency::ArtifactKind; +use crate::core::{Dependency, Target, TargetKind}; +use crate::CargoResult; +use std::collections::{HashMap, HashSet}; +use std::ffi::OsString; + +/// Return all environment variables for the given unit-dependencies +/// if artifacts are present. +pub fn get_env( + build_runner: &BuildRunner<'_, '_>, + dependencies: &[UnitDep], +) -> CargoResult> { + let mut env = HashMap::new(); + for unit_dep in dependencies.iter().filter(|d| d.unit.artifact.is_true()) { + for artifact_path in build_runner + .outputs(&unit_dep.unit)? + .iter() + .filter_map(|f| (f.flavor == FileFlavor::Normal).then(|| &f.path)) + { + let artifact_type_upper = unit_artifact_type_name_upper(&unit_dep.unit); + let dep_name = unit_dep.dep_name.unwrap_or(unit_dep.unit.pkg.name()); + let dep_name_upper = dep_name.to_uppercase().replace("-", "_"); + + let var = format!("CARGO_{}_DIR_{}", artifact_type_upper, dep_name_upper); + let path = artifact_path.parent().expect("parent dir for artifacts"); + env.insert(var, path.to_owned().into()); + + let var_file = format!( + "CARGO_{}_FILE_{}_{}", + artifact_type_upper, + dep_name_upper, + unit_dep.unit.target.name() + ); + + // In older releases, lib-targets defaulted to the name of the package. Newer releases + // use the same name as default, but with dashes replaced. Hence, if the name of the + // target was inferred by Cargo, we also set the env-var with the unconverted name for + // backwards compatibility. + let need_compat = unit_dep.unit.target.is_lib() && unit_dep.unit.target.name_inferred(); + if need_compat { + let var_compat = format!( + "CARGO_{}_FILE_{}_{}", + artifact_type_upper, + dep_name_upper, + unit_dep.unit.pkg.name(), + ); + if var_compat != var_file { + env.insert(var_compat, artifact_path.to_owned().into()); + } + } + + env.insert(var_file, artifact_path.to_owned().into()); + + // If the name of the target matches the name of the dependency, we strip the + // repetition and provide the simpler env-var as well. + // For backwards-compatibility of inferred names, we compare against the name of the + // package as well, since that used to be the default for library targets. + if unit_dep.unit.target.name() == dep_name.as_str() + || (need_compat && unit_dep.unit.pkg.name() == dep_name.as_str()) + { + let var = format!("CARGO_{}_FILE_{}", artifact_type_upper, dep_name_upper,); + env.insert(var, artifact_path.to_owned().into()); + } + } + } + Ok(env) +} + +fn unit_artifact_type_name_upper(unit: &Unit) -> &'static str { + match unit.target.kind() { + TargetKind::Lib(kinds) => match kinds.as_slice() { + &[CrateType::Cdylib] => "CDYLIB", + &[CrateType::Staticlib] => "STATICLIB", + invalid => unreachable!("BUG: artifacts cannot be of type {:?}", invalid), + }, + TargetKind::Bin => "BIN", + invalid => unreachable!("BUG: artifacts cannot be of type {:?}", invalid), + } +} + +/// Given a dependency with an artifact `artifact_dep` and a set of available `targets` +/// of its package, find a target for each kind of artifacts that are to be built. +/// +/// Failure to match any target results in an error mentioning the parent manifests +/// `parent_package` name. +pub(crate) fn match_artifacts_kind_with_targets<'t, 'd>( + artifact_dep: &'d Dependency, + targets: &'t [Target], + parent_package: &str, +) -> CargoResult> { + let mut out = HashSet::new(); + let artifact_requirements = artifact_dep.artifact().expect("artifact present"); + for artifact_kind in artifact_requirements.kinds() { + let mut extend = |kind, filter: &dyn Fn(&&Target) -> bool| { + let mut iter = targets.iter().filter(filter).peekable(); + let found = iter.peek().is_some(); + out.extend(std::iter::repeat(kind).zip(iter)); + found + }; + let found = match artifact_kind { + ArtifactKind::Cdylib => extend(artifact_kind, &|t| t.is_cdylib()), + ArtifactKind::Staticlib => extend(artifact_kind, &|t| t.is_staticlib()), + ArtifactKind::AllBinaries => extend(artifact_kind, &|t| t.is_bin()), + ArtifactKind::SelectedBinary(bin_name) => extend(artifact_kind, &|t| { + t.is_bin() && t.name() == bin_name.as_str() + }), + }; + if !found { + anyhow::bail!( + "dependency `{}` in package `{}` requires a `{}` artifact to be present.", + artifact_dep.name_in_toml(), + parent_package, + artifact_kind + ); + } + } + Ok(out) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_config.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_config.rs new file mode 100644 index 000000000..80aa592dd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_config.rs @@ -0,0 +1,274 @@ +use crate::core::compiler::CompileKind; +use crate::util::context::JobsConfig; +use crate::util::interning::InternedString; +use crate::util::{CargoResult, GlobalContext, RustfixDiagnosticServer}; +use anyhow::{bail, Context as _}; +use cargo_util::ProcessBuilder; +use serde::ser; +use std::cell::RefCell; +use std::path::PathBuf; +use std::rc::Rc; +use std::thread::available_parallelism; + +/// Configuration information for a rustc build. +#[derive(Debug, Clone)] +pub struct BuildConfig { + /// The requested kind of compilation for this session + pub requested_kinds: Vec, + /// Number of rustc jobs to run in parallel. + pub jobs: u32, + /// Do not abort the build as soon as there is an error. + pub keep_going: bool, + /// Build profile + pub requested_profile: InternedString, + /// The mode we are compiling in. + pub mode: CompileMode, + /// `true` to print stdout in JSON format (for machine reading). + pub message_format: MessageFormat, + /// Force Cargo to do a full rebuild and treat each target as changed. + pub force_rebuild: bool, + /// Output a build plan to stdout instead of actually compiling. + pub build_plan: bool, + /// Output the unit graph to stdout instead of actually compiling. + pub unit_graph: bool, + /// `true` to avoid really compiling. + pub dry_run: bool, + /// An optional override of the rustc process for primary units + pub primary_unit_rustc: Option, + /// 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 + /// `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, + /// Which kinds of build timings to output (empty if none). + pub timing_outputs: Vec, +} + +fn default_parallelism() -> CargoResult { + Ok(available_parallelism() + .context("failed to determine the amount of parallelism available")? + .get() as u32) +} + +impl BuildConfig { + /// Parses all config files to learn about build configuration. Currently + /// configured options are: + /// + /// * `build.jobs` + /// * `build.target` + /// * `target.$target.ar` + /// * `target.$target.linker` + /// * `target.$target.libfoo.metadata` + pub fn new( + gctx: &GlobalContext, + jobs: Option, + keep_going: bool, + requested_targets: &[String], + mode: CompileMode, + ) -> CargoResult { + let cfg = gctx.build_config()?; + let requested_kinds = CompileKind::from_requested_targets(gctx, requested_targets)?; + if jobs.is_some() && gctx.jobserver_from_env().is_some() { + gctx.shell().warn( + "a `-j` argument was passed to Cargo but Cargo is \ + also configured with an external jobserver in \ + its environment, ignoring the `-j` parameter", + )?; + } + let jobs = match jobs.or(cfg.jobs.clone()) { + None => default_parallelism()?, + Some(value) => match value { + JobsConfig::Integer(j) => match j { + 0 => anyhow::bail!("jobs may not be 0"), + j if j < 0 => (default_parallelism()? as i32 + j).max(1) as u32, + j => j as u32, + }, + JobsConfig::String(j) => match j.as_str() { + "default" => default_parallelism()?, + _ => { + anyhow::bail!( + format!("could not parse `{j}`. Number of parallel jobs should be `default` or a number.")) + } + }, + }, + }; + + Ok(BuildConfig { + requested_kinds, + jobs, + keep_going, + requested_profile: InternedString::new("dev"), + mode, + message_format: MessageFormat::Human, + force_rebuild: false, + build_plan: false, + unit_graph: false, + dry_run: false, + primary_unit_rustc: None, + rustfix_diagnostic_server: Rc::new(RefCell::new(None)), + export_dir: None, + future_incompat_report: false, + timing_outputs: Vec::new(), + }) + } + + /// Whether or not the *user* wants JSON output. Whether or not rustc + /// actually uses JSON is decided in `add_error_format`. + pub fn emit_json(&self) -> bool { + matches!(self.message_format, MessageFormat::Json { .. }) + } + + pub fn test(&self) -> bool { + self.mode == CompileMode::Test || self.mode == CompileMode::Bench + } + + pub fn single_requested_kind(&self) -> CargoResult { + match self.requested_kinds.len() { + 1 => Ok(self.requested_kinds[0]), + _ => bail!("only one `--target` argument is supported"), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum MessageFormat { + Human, + Json { + /// Whether rustc diagnostics are rendered by cargo or included into the + /// output stream. + render_diagnostics: bool, + /// Whether the `rendered` field of rustc diagnostics are using the + /// "short" rendering. + short: bool, + /// Whether the `rendered` field of rustc diagnostics embed ansi color + /// codes. + ansi: bool, + }, + Short, +} + +/// The general "mode" for what to do. +/// +/// This is used for two purposes. The commands themselves pass this in to +/// `compile_ws` to tell it the general execution strategy. This influences +/// the default targets selected. The other use is in the `Unit` struct +/// to indicate what is being done with a specific target. +#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)] +pub enum CompileMode { + /// A target being built for a test. + Test, + /// Building a target with `rustc` (lib or bin). + Build, + /// Building a target with `rustc` to emit `rmeta` metadata only. If + /// `test` is true, then it is also compiled with `--test` to check it like + /// a test. + Check { test: bool }, + /// Used to indicate benchmarks should be built. This is not used in + /// `Unit`, because it is essentially the same as `Test` (indicating + /// `--test` should be passed to rustc) and by using `Test` instead it + /// allows some de-duping of Units to occur. + Bench, + /// A target that will be documented with `rustdoc`. + + /// If `deps` is true, then it will also document all dependencies. + /// if `json` is true, the documentation output is in json format. + Doc { deps: bool, json: bool }, + /// A target that will be tested with `rustdoc`. + Doctest, + /// An example or library that will be scraped for function calls by `rustdoc`. + Docscrape, + /// A marker for Units that represent the execution of a `build.rs` script. + RunCustomBuild, +} + +impl ser::Serialize for CompileMode { + fn serialize(&self, s: S) -> Result + where + S: ser::Serializer, + { + use self::CompileMode::*; + match *self { + Test => "test".serialize(s), + Build => "build".serialize(s), + Check { .. } => "check".serialize(s), + Bench => "bench".serialize(s), + Doc { .. } => "doc".serialize(s), + Doctest => "doctest".serialize(s), + Docscrape => "docscrape".serialize(s), + RunCustomBuild => "run-custom-build".serialize(s), + } + } +} + +impl CompileMode { + /// Returns `true` if the unit is being checked. + pub fn is_check(self) -> bool { + matches!(self, CompileMode::Check { .. }) + } + + /// Returns `true` if this is generating documentation. + pub fn is_doc(self) -> bool { + matches!(self, CompileMode::Doc { .. }) + } + + /// Returns `true` if this a doc test. + pub fn is_doc_test(self) -> bool { + self == CompileMode::Doctest + } + + /// Returns `true` if this is scraping examples for documentation. + pub fn is_doc_scrape(self) -> bool { + self == CompileMode::Docscrape + } + + /// Returns `true` if this is any type of test (test, benchmark, doc test, or + /// check test). + pub fn is_any_test(self) -> bool { + matches!( + self, + CompileMode::Test + | CompileMode::Bench + | CompileMode::Check { test: true } + | CompileMode::Doctest + ) + } + + /// Returns `true` if this is something that passes `--test` to rustc. + pub fn is_rustc_test(self) -> bool { + matches!( + self, + CompileMode::Test | CompileMode::Bench | CompileMode::Check { test: true } + ) + } + + /// Returns `true` if this is the *execution* of a `build.rs` script. + pub fn is_run_custom_build(self) -> bool { + self == CompileMode::RunCustomBuild + } + + /// Returns `true` if this mode may generate an executable. + /// + /// Note that this also returns `true` for building libraries, so you also + /// have to check the target. + pub fn generates_executable(self) -> bool { + matches!( + self, + CompileMode::Test | CompileMode::Bench | CompileMode::Build + ) + } +} + +/// Kinds of build timings we can output. +#[derive(Clone, Copy, PartialEq, Debug, Eq, Hash, PartialOrd, Ord)] +pub enum TimingOutput { + /// Human-readable HTML report + Html, + /// Machine-readable JSON (unstable) + Json, +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/mod.rs new file mode 100644 index 000000000..8fbf05478 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/mod.rs @@ -0,0 +1,144 @@ +//! [`BuildContext`] is a (mostly) static information about a build task. + +use crate::core::compiler::unit_graph::UnitGraph; +use crate::core::compiler::{BuildConfig, CompileKind, Unit}; +use crate::core::profiles::Profiles; +use crate::core::PackageSet; +use crate::core::Workspace; +use crate::util::context::GlobalContext; +use crate::util::errors::CargoResult; +use crate::util::interning::InternedString; +use crate::util::Rustc; +use std::collections::{HashMap, HashSet}; + +mod target_info; +pub use self::target_info::{ + FileFlavor, FileType, RustDocFingerprint, RustcTargetData, TargetInfo, +}; + +/// The build context, containing complete information needed for a build task +/// before it gets started. +/// +/// It is intended that this is mostly static information. Stuff that mutates +/// during the build can be found in the parent [`BuildRunner`]. (I say mostly, +/// because this has internal caching, but nothing that should be observable +/// or require &mut.) +/// +/// As a result, almost every field on `BuildContext` is public, including +/// +/// * a resolved [`UnitGraph`] of your dependencies, +/// * a [`Profiles`] containing compiler flags presets, +/// * a [`RustcTargetData`] containing host and target platform information, +/// * and a [`PackageSet`] for further package downloads, +/// +/// just to name a few. Learn more on each own documentation. +/// +/// # How to use +/// +/// To prepare a build task, you may not want to use [`BuildContext::new`] directly, +/// since it is often too lower-level. +/// Instead, [`ops::create_bcx`] is usually what you are looking for. +/// +/// After a `BuildContext` is built, the next stage of building is handled in [`BuildRunner`]. +/// +/// [`BuildRunner`]: crate::core::compiler::BuildRunner +/// [`ops::create_bcx`]: crate::ops::create_bcx +pub struct BuildContext<'a, 'gctx> { + /// The workspace the build is for. + pub ws: &'a Workspace<'gctx>, + + /// The cargo context. + pub gctx: &'gctx GlobalContext, + + /// This contains a collection of compiler flags presets. + pub profiles: Profiles, + + /// Configuration information for a rustc build. + pub build_config: &'a BuildConfig, + + /// Extra compiler args for either `rustc` or `rustdoc`. + pub extra_compiler_args: HashMap>, + + /// Package downloader. + /// + /// This holds ownership of the `Package` objects. + pub packages: PackageSet<'gctx>, + + /// Information about rustc and the target platform. + pub target_data: RustcTargetData<'gctx>, + + /// The root units of `unit_graph` (units requested on the command-line). + pub roots: Vec, + + /// The dependency graph of units to compile. + pub unit_graph: UnitGraph, + + /// Reverse-dependencies of documented units, used by the `rustdoc --scrape-examples` flag. + pub scrape_units: Vec, + + /// The list of all kinds that are involved in this build + pub all_kinds: HashSet, +} + +impl<'a, 'gctx> BuildContext<'a, 'gctx> { + pub fn new( + ws: &'a Workspace<'gctx>, + packages: PackageSet<'gctx>, + build_config: &'a BuildConfig, + profiles: Profiles, + extra_compiler_args: HashMap>, + target_data: RustcTargetData<'gctx>, + roots: Vec, + unit_graph: UnitGraph, + scrape_units: Vec, + ) -> CargoResult> { + let all_kinds = unit_graph + .keys() + .map(|u| u.kind) + .chain(build_config.requested_kinds.iter().copied()) + .chain(std::iter::once(CompileKind::Host)) + .collect(); + + Ok(BuildContext { + ws, + gctx: ws.gctx(), + packages, + build_config, + profiles, + extra_compiler_args, + target_data, + roots, + unit_graph, + scrape_units, + all_kinds, + }) + } + + /// Information of the `rustc` this build task will use. + pub fn rustc(&self) -> &Rustc { + &self.target_data.rustc + } + + /// Gets the host architecture triple. + /// + /// For example, `x86_64-unknown-linux-gnu`, would be + /// - machine: `x86_64`, + /// - hardware-platform: `unknown`, + /// - operating system: `linux-gnu`. + pub fn host_triple(&self) -> InternedString { + self.target_data.rustc.host + } + + /// Gets the number of jobs specified for this build. + pub fn jobs(&self) -> u32 { + self.build_config.jobs + } + + /// Extra compiler args for either `rustc` or `rustdoc`. + /// + /// As of now, these flags come from the trailing args of either + /// `cargo rustc` or `cargo rustdoc`. + pub fn extra_args_for(&self, unit: &Unit) -> Option<&Vec> { + self.extra_compiler_args.get(unit) + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/target_info.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/target_info.rs new file mode 100644 index 000000000..6a0bea3f7 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_context/target_info.rs @@ -0,0 +1,1197 @@ +//! This modules contains types storing information of target platforms. +//! +//! Normally, call [`RustcTargetData::new`] to construct all the target +//! platform once, and then query info on your demand. For example, +//! +//! * [`RustcTargetData::dep_platform_activated`] to check if platform is activated. +//! * [`RustcTargetData::info`] to get a [`TargetInfo`] for an in-depth query. +//! * [`TargetInfo::rustc_outputs`] to get a list of supported file types. + +use crate::core::compiler::apply_env_config; +use crate::core::compiler::{BuildRunner, CompileKind, CompileMode, CompileTarget, CrateType}; +use crate::core::{Dependency, Package, Target, TargetKind, Workspace}; +use crate::util::context::{GlobalContext, StringList, TargetConfig}; +use crate::util::interning::InternedString; +use crate::util::{CargoResult, Rustc}; +use anyhow::Context as _; +use cargo_platform::{Cfg, CfgExpr}; +use cargo_util::{paths, ProcessBuilder}; +use serde::{Deserialize, Serialize}; +use std::cell::RefCell; +use std::collections::hash_map::{Entry, HashMap}; +use std::path::{Path, PathBuf}; +use std::rc::Rc; +use std::str::{self, FromStr}; + +/// Information about the platform target gleaned from querying rustc. +/// +/// [`RustcTargetData`] keeps several of these, one for the host and the others +/// for other specified targets. If no target is specified, it uses a clone from +/// the host. +#[derive(Clone)] +pub struct TargetInfo { + /// A base process builder for discovering crate type information. In + /// particular, this is used to determine the output filename prefix and + /// suffix for a crate type. + crate_type_process: ProcessBuilder, + /// Cache of output filename prefixes and suffixes. + /// + /// The key is the crate type name (like `cdylib`) and the value is + /// `Some((prefix, suffix))`, for example `libcargo.so` would be + /// `Some(("lib", ".so"))`. The value is `None` if the crate type is not + /// supported. + crate_types: RefCell>>, + /// `cfg` information extracted from `rustc --print=cfg`. + cfg: Vec, + /// `supports_std` information extracted from `rustc --print=target-spec-json` + pub supports_std: Option, + /// Supported values for `-Csplit-debuginfo=` flag, queried from rustc + support_split_debuginfo: Vec, + /// Path to the sysroot. + pub sysroot: PathBuf, + /// Path to the "lib" directory in the sysroot which rustc uses for linking + /// target libraries. + pub sysroot_target_libdir: PathBuf, + /// Extra flags to pass to `rustc`, see [`extra_args`]. + pub rustflags: Rc<[String]>, + /// Extra flags to pass to `rustdoc`, see [`extra_args`]. + pub rustdocflags: Rc<[String]>, +} + +/// Kind of each file generated by a Unit, part of `FileType`. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum FileFlavor { + /// Not a special file type. + Normal, + /// Like `Normal`, but not directly executable. + /// For example, a `.wasm` file paired with the "normal" `.js` file. + Auxiliary, + /// Something you can link against (e.g., a library). + Linkable, + /// An `.rmeta` Rust metadata file. + Rmeta, + /// Piece of external debug information (e.g., `.dSYM`/`.pdb` file). + DebugInfo, +} + +/// Type of each file generated by a Unit. +#[derive(Debug)] +pub struct FileType { + /// The kind of file. + pub flavor: FileFlavor, + /// The crate-type that generates this file. + /// + /// `None` for things that aren't associated with a specific crate type, + /// for example `rmeta` files. + pub crate_type: Option, + /// The suffix for the file (for example, `.rlib`). + /// This is an empty string for executables on Unix-like platforms. + suffix: String, + /// The prefix for the file (for example, `lib`). + /// This is an empty string for things like executables. + prefix: String, + /// Flag to convert hyphen to underscore when uplifting. + should_replace_hyphens: bool, +} + +impl FileType { + /// The filename for this `FileType` crated by rustc. + pub fn output_filename(&self, target: &Target, metadata: Option<&str>) -> String { + match metadata { + Some(metadata) => format!( + "{}{}-{}{}", + self.prefix, + target.crate_name(), + metadata, + self.suffix + ), + None => format!("{}{}{}", self.prefix, target.crate_name(), self.suffix), + } + } + + /// The filename for this `FileType` that Cargo should use when "uplifting" + /// it to the destination directory. + pub fn uplift_filename(&self, target: &Target) -> String { + let name = match target.binary_filename() { + Some(name) => name, + None => { + // For binary crate type, `should_replace_hyphens` will always be false. + if self.should_replace_hyphens { + target.crate_name() + } else { + target.name().to_string() + } + } + }; + + format!("{}{}{}", self.prefix, name, self.suffix) + } + + /// Creates a new instance representing a `.rmeta` file. + pub fn new_rmeta() -> FileType { + // Note that even binaries use the `lib` prefix. + FileType { + flavor: FileFlavor::Rmeta, + crate_type: None, + suffix: ".rmeta".to_string(), + prefix: "lib".to_string(), + should_replace_hyphens: true, + } + } +} + +impl TargetInfo { + /// Learns the information of target platform from `rustc` invocation(s). + /// + /// Generally, the first time calling this function is expensive, as it may + /// query `rustc` several times. To reduce the cost, output of each `rustc` + /// invocation is cached by [`Rustc::cached_output`]. + /// + /// Search `Tricky` to learn why querying `rustc` several times is needed. + #[tracing::instrument(skip_all)] + pub fn new( + gctx: &GlobalContext, + requested_kinds: &[CompileKind], + rustc: &Rustc, + kind: CompileKind, + ) -> CargoResult { + let mut rustflags = + extra_args(gctx, requested_kinds, &rustc.host, None, kind, Flags::Rust)?; + let mut turn = 0; + loop { + let extra_fingerprint = kind.fingerprint_hash(); + + // Query rustc for several kinds of info from each line of output: + // 0) file-names (to determine output file prefix/suffix for given crate type) + // 1) sysroot + // 2) split-debuginfo + // 3) cfg + // + // Search `--print` to see what we query so far. + let mut process = rustc.workspace_process(); + apply_env_config(gctx, &mut process)?; + process + .arg("-") + .arg("--crate-name") + .arg("___") + .arg("--print=file-names") + .args(&rustflags) + .env_remove("RUSTC_LOG"); + + // Removes `FD_CLOEXEC` set by `jobserver::Client` to pass jobserver + // as environment variables specify. + if let Some(client) = gctx.jobserver_from_env() { + process.inherit_jobserver(client); + } + + if let CompileKind::Target(target) = kind { + process.arg("--target").arg(target.rustc_target()); + } + + let crate_type_process = process.clone(); + const KNOWN_CRATE_TYPES: &[CrateType] = &[ + CrateType::Bin, + CrateType::Rlib, + CrateType::Dylib, + CrateType::Cdylib, + CrateType::Staticlib, + CrateType::ProcMacro, + ]; + for crate_type in KNOWN_CRATE_TYPES.iter() { + process.arg("--crate-type").arg(crate_type.as_str()); + } + + process.arg("--print=sysroot"); + process.arg("--print=split-debuginfo"); + process.arg("--print=crate-name"); // `___` as a delimiter. + process.arg("--print=cfg"); + + // parse_crate_type() relies on "unsupported/unknown crate type" error message, + // so make warnings always emitted as warnings. + process.arg("-Wwarnings"); + + let (output, error) = rustc + .cached_output(&process, extra_fingerprint) + .with_context(|| { + "failed to run `rustc` to learn about target-specific information" + })?; + + let mut lines = output.lines(); + let mut map = HashMap::new(); + for crate_type in KNOWN_CRATE_TYPES { + let out = parse_crate_type(crate_type, &process, &output, &error, &mut lines)?; + map.insert(crate_type.clone(), out); + } + + let Some(line) = lines.next() else { + return error_missing_print_output("sysroot", &process, &output, &error); + }; + let sysroot = PathBuf::from(line); + let sysroot_target_libdir = { + let mut libdir = sysroot.clone(); + libdir.push("lib"); + libdir.push("rustlib"); + libdir.push(match &kind { + CompileKind::Host => rustc.host.as_str(), + CompileKind::Target(target) => target.short_name(), + }); + libdir.push("lib"); + libdir + }; + + let support_split_debuginfo = { + // HACK: abuse `--print=crate-name` to use `___` as a delimiter. + let mut res = Vec::new(); + loop { + match lines.next() { + Some(line) if line == "___" => break, + Some(line) => res.push(line.into()), + None => { + return error_missing_print_output( + "split-debuginfo", + &process, + &output, + &error, + ) + } + } + } + res + }; + + let cfg = lines + .map(|line| Ok(Cfg::from_str(line)?)) + .filter(TargetInfo::not_user_specific_cfg) + .collect::>>() + .with_context(|| { + format!( + "failed to parse the cfg from `rustc --print=cfg`, got:\n{}", + output + ) + })?; + + // recalculate `rustflags` from above now that we have `cfg` + // information + let new_flags = extra_args( + gctx, + requested_kinds, + &rustc.host, + Some(&cfg), + kind, + Flags::Rust, + )?; + + // Tricky: `RUSTFLAGS` defines the set of active `cfg` flags, active + // `cfg` flags define which `.cargo/config` sections apply, and they + // in turn can affect `RUSTFLAGS`! This is a bona fide mutual + // dependency, and it can even diverge (see `cfg_paradox` test). + // + // So what we do here is running at most *two* iterations of + // fixed-point iteration, which should be enough to cover + // practically useful cases, and warn if that's not enough for + // convergence. + let reached_fixed_point = new_flags == rustflags; + if !reached_fixed_point && turn == 0 { + turn += 1; + rustflags = new_flags; + continue; + } + if !reached_fixed_point { + gctx.shell().warn("non-trivial mutual dependency between target-specific configuration and RUSTFLAGS")?; + } + + let mut supports_std: Option = None; + + // The '--print=target-spec-json' is an unstable option of rustc, therefore only + // try to fetch this information if rustc allows nightly features. Additionally, + // to avoid making two rustc queries when not required, only try to fetch the + // target-spec when the '-Zbuild-std' option is passed. + if gctx.cli_unstable().build_std.is_some() { + let mut target_spec_process = rustc.workspace_process(); + apply_env_config(gctx, &mut target_spec_process)?; + target_spec_process + .arg("--print=target-spec-json") + .arg("-Zunstable-options") + .args(&rustflags) + .env_remove("RUSTC_LOG"); + + if let CompileKind::Target(target) = kind { + target_spec_process + .arg("--target") + .arg(target.rustc_target()); + } + + #[derive(Deserialize)] + struct Metadata { + pub std: Option, + } + + #[derive(Deserialize)] + struct TargetSpec { + pub metadata: Metadata, + } + + if let Ok(output) = target_spec_process.output() { + if let Ok(spec) = serde_json::from_slice::(&output.stdout) { + supports_std = spec.metadata.std; + } + } + } + + return Ok(TargetInfo { + crate_type_process, + crate_types: RefCell::new(map), + sysroot, + sysroot_target_libdir, + rustflags: rustflags.into(), + rustdocflags: extra_args( + gctx, + requested_kinds, + &rustc.host, + Some(&cfg), + kind, + Flags::Rustdoc, + )? + .into(), + cfg, + supports_std, + support_split_debuginfo, + }); + } + } + + fn not_user_specific_cfg(cfg: &CargoResult) -> bool { + if let Ok(Cfg::Name(cfg_name)) = cfg { + // This should also include "debug_assertions", but it causes + // regressions. Maybe some day in the distant future it can be + // added (and possibly change the warning to an error). + if cfg_name == "proc_macro" { + return false; + } + } + true + } + + /// All the target [`Cfg`] settings. + pub fn cfg(&self) -> &[Cfg] { + &self.cfg + } + + /// Returns the list of file types generated by the given crate type. + /// + /// Returns `None` if the target does not support the given crate type. + fn file_types( + &self, + crate_type: &CrateType, + flavor: FileFlavor, + target_triple: &str, + ) -> CargoResult>> { + let crate_type = if *crate_type == CrateType::Lib { + CrateType::Rlib + } else { + crate_type.clone() + }; + + let mut crate_types = self.crate_types.borrow_mut(); + let entry = crate_types.entry(crate_type.clone()); + let crate_type_info = match entry { + Entry::Occupied(o) => &*o.into_mut(), + Entry::Vacant(v) => { + let value = self.discover_crate_type(v.key())?; + &*v.insert(value) + } + }; + let Some((prefix, suffix)) = crate_type_info else { + return Ok(None); + }; + let mut ret = vec![FileType { + suffix: suffix.clone(), + prefix: prefix.clone(), + flavor, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: crate_type != CrateType::Bin, + }]; + + // Window shared library import/export files. + if crate_type.is_dynamic() { + // Note: Custom JSON specs can alter the suffix. For now, we'll + // just ignore non-DLL suffixes. + if target_triple.ends_with("-windows-msvc") && suffix == ".dll" { + // See https://docs.microsoft.com/en-us/cpp/build/reference/working-with-import-libraries-and-export-files + // for more information about DLL import/export files. + ret.push(FileType { + suffix: ".dll.lib".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }); + // NOTE: lld does not produce these + ret.push(FileType { + suffix: ".dll.exp".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }); + } else if suffix == ".dll" + && (target_triple.ends_with("windows-gnu") + || target_triple.ends_with("windows-gnullvm")) + { + // See https://cygwin.com/cygwin-ug-net/dll.html for more + // information about GNU import libraries. + // LD can link DLL directly, but LLD requires the import library. + ret.push(FileType { + suffix: ".dll.a".to_string(), + prefix: "lib".to_string(), + flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }) + } + } + + if target_triple.starts_with("wasm32-") && crate_type == CrateType::Bin && suffix == ".js" { + // emscripten binaries generate a .js file, which loads a .wasm + // file. + ret.push(FileType { + suffix: ".wasm".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::Auxiliary, + crate_type: Some(crate_type.clone()), + // Name `foo-bar` will generate a `foo_bar.js` and + // `foo_bar.wasm`. Cargo will translate the underscore and + // copy `foo_bar.js` to `foo-bar.js`. However, the wasm + // filename is embedded in the .js file with an underscore, so + // it should not contain hyphens. + should_replace_hyphens: true, + }); + // And a map file for debugging. This is only emitted with debug=2 + // (-g4 for emcc). + ret.push(FileType { + suffix: ".wasm.map".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::DebugInfo, + crate_type: Some(crate_type.clone()), + should_replace_hyphens: true, + }); + } + + // Handle separate debug files. + let is_apple = target_triple.contains("-apple-"); + if matches!( + crate_type, + CrateType::Bin | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro + ) { + if is_apple { + let suffix = if crate_type == CrateType::Bin { + ".dSYM".to_string() + } else { + ".dylib.dSYM".to_string() + }; + ret.push(FileType { + suffix, + prefix: prefix.clone(), + flavor: FileFlavor::DebugInfo, + crate_type: Some(crate_type), + // macOS tools like lldb use all sorts of magic to locate + // dSYM files. See https://lldb.llvm.org/use/symbols.html + // for some details. It seems like a `.dSYM` located next + // to the executable with the same name is one method. The + // dSYM should have the same hyphens as the executable for + // the names to match. + should_replace_hyphens: false, + }) + } else if target_triple.ends_with("-msvc") || target_triple.ends_with("-uefi") { + ret.push(FileType { + suffix: ".pdb".to_string(), + prefix: prefix.clone(), + flavor: FileFlavor::DebugInfo, + crate_type: Some(crate_type), + // The absolute path to the pdb file is embedded in the + // executable. If the exe/pdb pair is moved to another + // machine, then debuggers will look in the same directory + // of the exe with the original pdb filename. Since the + // original name contains underscores, they need to be + // preserved. + should_replace_hyphens: true, + }) + } else { + // Because DWARF Package (dwp) files are produced after the + // fact by another tool, there is nothing in the binary that + // provides a means to locate them. By convention, debuggers + // take the binary filename and append ".dwp" (including to + // binaries that already have an extension such as shared libs) + // to find the dwp. + ret.push(FileType { + // It is important to preserve the existing suffix for + // e.g. shared libraries, where the dwp for libfoo.so is + // expected to be at libfoo.so.dwp. + suffix: format!("{suffix}.dwp"), + prefix: prefix.clone(), + flavor: FileFlavor::DebugInfo, + crate_type: Some(crate_type.clone()), + // Likewise, the dwp needs to match the primary artifact's + // hyphenation exactly. + should_replace_hyphens: crate_type != CrateType::Bin, + }) + } + } + + Ok(Some(ret)) + } + + fn discover_crate_type(&self, crate_type: &CrateType) -> CargoResult> { + let mut process = self.crate_type_process.clone(); + + process.arg("--crate-type").arg(crate_type.as_str()); + + let output = process.exec_with_output().with_context(|| { + format!( + "failed to run `rustc` to learn about crate-type {} information", + crate_type + ) + })?; + + let error = str::from_utf8(&output.stderr).unwrap(); + let output = str::from_utf8(&output.stdout).unwrap(); + parse_crate_type(crate_type, &process, output, error, &mut output.lines()) + } + + /// Returns all the file types generated by rustc for the given `mode`/`target_kind`. + /// + /// The first value is a Vec of file types generated, the second value is + /// a list of `CrateTypes` that are not supported by the given target. + pub fn rustc_outputs( + &self, + mode: CompileMode, + target_kind: &TargetKind, + target_triple: &str, + ) -> CargoResult<(Vec, Vec)> { + match mode { + CompileMode::Build => self.calc_rustc_outputs(target_kind, target_triple), + CompileMode::Test | CompileMode::Bench => { + match self.file_types(&CrateType::Bin, FileFlavor::Normal, target_triple)? { + Some(fts) => Ok((fts, Vec::new())), + None => Ok((Vec::new(), vec![CrateType::Bin])), + } + } + CompileMode::Check { .. } => Ok((vec![FileType::new_rmeta()], Vec::new())), + CompileMode::Doc { .. } + | CompileMode::Doctest + | CompileMode::Docscrape + | CompileMode::RunCustomBuild => { + panic!("asked for rustc output for non-rustc mode") + } + } + } + + fn calc_rustc_outputs( + &self, + target_kind: &TargetKind, + target_triple: &str, + ) -> CargoResult<(Vec, Vec)> { + let mut unsupported = Vec::new(); + let mut result = Vec::new(); + let crate_types = target_kind.rustc_crate_types(); + for crate_type in &crate_types { + let flavor = if crate_type.is_linkable() { + FileFlavor::Linkable + } else { + FileFlavor::Normal + }; + let file_types = self.file_types(crate_type, flavor, target_triple)?; + match file_types { + Some(types) => { + result.extend(types); + } + None => { + unsupported.push(crate_type.clone()); + } + } + } + if !result.is_empty() && !crate_types.iter().any(|ct| ct.requires_upstream_objects()) { + // Only add rmeta if pipelining. + result.push(FileType::new_rmeta()); + } + Ok((result, unsupported)) + } + + /// Checks if the debuginfo-split value is supported by this target + pub fn supports_debuginfo_split(&self, split: InternedString) -> bool { + self.support_split_debuginfo + .iter() + .any(|sup| sup.as_str() == split.as_str()) + } + + /// Checks if a target maybe support std. + /// + /// If no explictly stated in target spec json, we treat it as "maybe support". + /// + /// This is only useful for `-Zbuild-std` to determine the default set of + /// crates it is going to build. + pub fn maybe_support_std(&self) -> bool { + matches!(self.supports_std, Some(true) | None) + } +} + +/// Takes rustc output (using specialized command line args), and calculates the file prefix and +/// suffix for the given crate type, or returns `None` if the type is not supported. (e.g., for a +/// Rust library like `libcargo.rlib`, we have prefix "lib" and suffix "rlib"). +/// +/// The caller needs to ensure that the lines object is at the correct line for the given crate +/// type: this is not checked. +/// +/// This function can not handle more than one file per type (with wasm32-unknown-emscripten, there +/// are two files for bin (`.wasm` and `.js`)). +fn parse_crate_type( + crate_type: &CrateType, + cmd: &ProcessBuilder, + output: &str, + error: &str, + lines: &mut str::Lines<'_>, +) -> CargoResult> { + let not_supported = error.lines().any(|line| { + (line.contains("unsupported crate type") || line.contains("unknown crate type")) + && line.contains(&format!("crate type `{}`", crate_type)) + }); + if not_supported { + return Ok(None); + } + 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(); + let Some(suffix) = parts.next() else { + return error_missing_print_output("file-names", cmd, output, error); + }; + + Ok(Some((prefix.to_string(), suffix.to_string()))) +} + +/// Helper for creating an error message for missing output from a certain `--print` request. +fn error_missing_print_output( + request: &str, + cmd: &ProcessBuilder, + stdout: &str, + stderr: &str, +) -> CargoResult { + let err_info = output_err_info(cmd, stdout, stderr); + anyhow::bail!( + "output of --print={request} missing when learning about \ + target-specific information from rustc\n{err_info}", + ) +} + +/// Helper for creating an error message when parsing rustc output fails. +fn output_err_info(cmd: &ProcessBuilder, stdout: &str, stderr: &str) -> String { + let mut result = format!("command was: {}\n", cmd); + if !stdout.is_empty() { + result.push_str("\n--- stdout\n"); + result.push_str(stdout); + } + if !stderr.is_empty() { + result.push_str("\n--- stderr\n"); + result.push_str(stderr); + } + if stdout.is_empty() && stderr.is_empty() { + result.push_str("(no output received)"); + } + result +} + +/// Compiler flags for either rustc or rustdoc. +#[derive(Debug, Copy, Clone)] +enum Flags { + Rust, + Rustdoc, +} + +impl Flags { + fn as_key(self) -> &'static str { + match self { + Flags::Rust => "rustflags", + Flags::Rustdoc => "rustdocflags", + } + } + + fn as_env(self) -> &'static str { + match self { + Flags::Rust => "RUSTFLAGS", + Flags::Rustdoc => "RUSTDOCFLAGS", + } + } +} + +/// Acquire extra flags to pass to the compiler from various locations. +/// +/// The locations are: +/// +/// - the `CARGO_ENCODED_RUSTFLAGS` environment variable +/// - the `RUSTFLAGS` environment variable +/// +/// then if none of those were found +/// +/// - `target.*.rustflags` from the config (.cargo/config) +/// - `target.cfg(..).rustflags` from the config +/// - `host.*.rustflags` from the config if compiling a host artifact or without `--target` +/// (requires `-Zhost-config`) +/// +/// then if none of those were found +/// +/// - `build.rustflags` from the config +/// +/// The behavior differs slightly when cross-compiling (or, specifically, when `--target` is +/// provided) for artifacts that are always built for the host (plugins, build scripts, ...). +/// For those artifacts, _only_ `host.*.rustflags` is respected, and no other configuration +/// sources, _regardless of the value of `target-applies-to-host`_. This is counterintuitive, but +/// necessary to retain backwards compatibility with older versions of Cargo. +/// +/// Rules above also applies to rustdoc. Just the key would be `rustdocflags`/`RUSTDOCFLAGS`. +fn extra_args( + gctx: &GlobalContext, + requested_kinds: &[CompileKind], + host_triple: &str, + target_cfg: Option<&[Cfg]>, + kind: CompileKind, + flags: Flags, +) -> CargoResult> { + let target_applies_to_host = gctx.target_applies_to_host()?; + + // Host artifacts should not generally pick up rustflags from anywhere except [host]. + // + // The one exception to this is if `target-applies-to-host = true`, which opts into a + // particular (inconsistent) past Cargo behavior where host artifacts _do_ pick up rustflags + // set elsewhere when `--target` isn't passed. + if kind.is_host() { + if target_applies_to_host && requested_kinds == [CompileKind::Host] { + // This is the past Cargo behavior where we fall back to the same logic as for other + // artifacts without --target. + } else { + // In all other cases, host artifacts just get flags from [host], regardless of + // --target. Or, phrased differently, no `--target` behaves the same as `--target + // `, and host artifacts are always "special" (they don't pick up `RUSTFLAGS` for + // example). + return Ok(rustflags_from_host(gctx, flags, host_triple)?.unwrap_or_else(Vec::new)); + } + } + + // All other artifacts pick up the RUSTFLAGS, [target.*], and [build], in that order. + // NOTE: It is impossible to have a [host] section and reach this logic with kind.is_host(), + // since [host] implies `target-applies-to-host = false`, which always early-returns above. + + if let Some(rustflags) = rustflags_from_env(gctx, flags) { + Ok(rustflags) + } else if let Some(rustflags) = + rustflags_from_target(gctx, host_triple, target_cfg, kind, flags)? + { + Ok(rustflags) + } else if let Some(rustflags) = rustflags_from_build(gctx, flags)? { + Ok(rustflags) + } else { + Ok(Vec::new()) + } +} + +/// Gets compiler flags from environment variables. +/// See [`extra_args`] for more. +fn rustflags_from_env(gctx: &GlobalContext, flags: Flags) -> Option> { + // First try CARGO_ENCODED_RUSTFLAGS from the environment. + // Prefer this over RUSTFLAGS since it's less prone to encoding errors. + if let Ok(a) = gctx.get_env(format!("CARGO_ENCODED_{}", flags.as_env())) { + if a.is_empty() { + return Some(Vec::new()); + } + return Some(a.split('\x1f').map(str::to_string).collect()); + } + + // Then try RUSTFLAGS from the environment + if let Ok(a) = gctx.get_env(flags.as_env()) { + let args = a + .split(' ') + .map(str::trim) + .filter(|s| !s.is_empty()) + .map(str::to_string); + return Some(args.collect()); + } + + // No rustflags to be collected from the environment + None +} + +/// Gets compiler flags from `[target]` section in the config. +/// See [`extra_args`] for more. +fn rustflags_from_target( + gctx: &GlobalContext, + host_triple: &str, + target_cfg: Option<&[Cfg]>, + kind: CompileKind, + flag: Flags, +) -> CargoResult>> { + let mut rustflags = Vec::new(); + + // Then the target.*.rustflags value... + let target = match &kind { + CompileKind::Host => host_triple, + CompileKind::Target(target) => target.short_name(), + }; + let key = format!("target.{}.{}", target, flag.as_key()); + if let Some(args) = gctx.get::>(&key)? { + rustflags.extend(args.as_slice().iter().cloned()); + } + // ...including target.'cfg(...)'.rustflags + if let Some(target_cfg) = target_cfg { + gctx.target_cfgs()? + .iter() + .filter_map(|(key, cfg)| { + match flag { + Flags::Rust => cfg + .rustflags + .as_ref() + .map(|rustflags| (key, &rustflags.val)), + // `target.cfg(…).rustdocflags` is currently not supported. + Flags::Rustdoc => None, + } + }) + .filter(|(key, _rustflags)| CfgExpr::matches_key(key, target_cfg)) + .for_each(|(_key, cfg_rustflags)| { + rustflags.extend(cfg_rustflags.as_slice().iter().cloned()); + }); + } + + if rustflags.is_empty() { + Ok(None) + } else { + Ok(Some(rustflags)) + } +} + +/// Gets compiler flags from `[host]` section in the config. +/// See [`extra_args`] for more. +fn rustflags_from_host( + gctx: &GlobalContext, + flag: Flags, + host_triple: &str, +) -> CargoResult>> { + let target_cfg = gctx.host_cfg_triple(host_triple)?; + let list = match flag { + Flags::Rust => &target_cfg.rustflags, + Flags::Rustdoc => { + // host.rustdocflags is not a thing, since it does not make sense + return Ok(None); + } + }; + Ok(list.as_ref().map(|l| l.val.as_slice().to_vec())) +} + +/// Gets compiler flags from `[build]` section in the config. +/// See [`extra_args`] for more. +fn rustflags_from_build(gctx: &GlobalContext, flag: Flags) -> CargoResult>> { + // Then the `build.rustflags` value. + let build = gctx.build_config()?; + let list = match flag { + Flags::Rust => &build.rustflags, + Flags::Rustdoc => &build.rustdocflags, + }; + Ok(list.as_ref().map(|l| l.as_slice().to_vec())) +} + +/// Collection of information about `rustc` and the host and target. +pub struct RustcTargetData<'gctx> { + /// Information about `rustc` itself. + pub rustc: Rustc, + + /// Config + pub gctx: &'gctx GlobalContext, + requested_kinds: Vec, + + /// Build information for the "host", which is information about when + /// `rustc` is invoked without a `--target` flag. This is used for + /// selecting a linker, and applying link overrides. + /// + /// The configuration read into this depends on whether or not + /// `target-applies-to-host=true`. + host_config: TargetConfig, + /// Information about the host platform. + host_info: TargetInfo, + + /// Build information for targets that we're building for. + target_config: HashMap, + /// Information about the target platform that we're building for. + target_info: HashMap, +} + +impl<'gctx> RustcTargetData<'gctx> { + #[tracing::instrument(skip_all)] + pub fn new( + ws: &Workspace<'gctx>, + requested_kinds: &[CompileKind], + ) -> CargoResult> { + let gctx = ws.gctx(); + let rustc = gctx.load_global_rustc(Some(ws))?; + let mut target_config = HashMap::new(); + let mut target_info = HashMap::new(); + let target_applies_to_host = gctx.target_applies_to_host()?; + let host_target = CompileTarget::new(&rustc.host)?; + let host_info = TargetInfo::new(gctx, requested_kinds, &rustc, CompileKind::Host)?; + + // This config is used for link overrides and choosing a linker. + let host_config = if target_applies_to_host { + gctx.target_cfg_triple(&rustc.host)? + } else { + gctx.host_cfg_triple(&rustc.host)? + }; + + // This is a hack. The unit_dependency graph builder "pretends" that + // `CompileKind::Host` is `CompileKind::Target(host)` if the + // `--target` flag is not specified. Since the unit_dependency code + // needs access to the target config data, create a copy so that it + // can be found. See `rebuild_unit_graph_shared` for why this is done. + if requested_kinds.iter().any(CompileKind::is_host) { + target_config.insert(host_target, gctx.target_cfg_triple(&rustc.host)?); + + // If target_applies_to_host is true, the host_info is the target info, + // otherwise we need to build target info for the target. + if target_applies_to_host { + target_info.insert(host_target, host_info.clone()); + } else { + let host_target_info = TargetInfo::new( + gctx, + requested_kinds, + &rustc, + CompileKind::Target(host_target), + )?; + target_info.insert(host_target, host_target_info); + } + }; + + let mut res = RustcTargetData { + rustc, + gctx, + requested_kinds: requested_kinds.into(), + host_config, + host_info, + target_config, + target_info, + }; + + // Get all kinds we currently know about. + // + // For now, targets can only ever come from the root workspace + // units and artifact dependencies, so this + // correctly represents all the kinds that can happen. When we have + // other ways for targets to appear at places that are not the root units, + // we may have to revisit this. + fn artifact_targets(package: &Package) -> impl Iterator + '_ { + package + .manifest() + .dependencies() + .iter() + .filter_map(|d| d.artifact()?.target()?.to_compile_kind()) + } + let all_kinds = requested_kinds + .iter() + .copied() + .chain(ws.members().flat_map(|p| { + p.manifest() + .default_kind() + .into_iter() + .chain(p.manifest().forced_kind()) + .chain(artifact_targets(p)) + })); + for kind in all_kinds { + res.merge_compile_kind(kind)?; + } + + Ok(res) + } + + /// Insert `kind` into our `target_info` and `target_config` members if it isn't present yet. + 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 + .insert(target, self.gctx.target_cfg_triple(target.short_name())?); + } + if !self.target_info.contains_key(&target) { + self.target_info.insert( + target, + TargetInfo::new(self.gctx, &self.requested_kinds, &self.rustc, kind)?, + ); + } + } + Ok(()) + } + + /// Returns a "short" name for the given kind, suitable for keying off + /// configuration in Cargo or presenting to users. + pub fn short_name<'a>(&'a self, kind: &'a CompileKind) -> &'a str { + match kind { + CompileKind::Host => &self.rustc.host, + CompileKind::Target(target) => target.short_name(), + } + } + + /// Whether a dependency should be compiled for the host or target platform, + /// specified by `CompileKind`. + 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 Some(platform) = dep.platform() else { + return true; + }; + let name = self.short_name(&kind); + platform.matches(name, self.cfg(kind)) + } + + /// Gets the list of `cfg`s printed out from the compiler for the specified kind. + pub fn cfg(&self, kind: CompileKind) -> &[Cfg] { + self.info(kind).cfg() + } + + /// Information about the given target platform, learned by querying rustc. + /// + /// # Panics + /// + /// Panics, if the target platform described by `kind` can't be found. + /// See [`get_info`](Self::get_info) for a non-panicking alternative. + pub fn info(&self, kind: CompileKind) -> &TargetInfo { + self.get_info(kind).unwrap() + } + + /// Information about the given target platform, learned by querying rustc. + /// + /// Returns `None` if the target platform described by `kind` can't be found. + pub fn get_info(&self, kind: CompileKind) -> Option<&TargetInfo> { + match kind { + CompileKind::Host => Some(&self.host_info), + CompileKind::Target(s) => self.target_info.get(&s), + } + } + + /// Gets the target configuration for a particular host or target. + pub fn target_config(&self, kind: CompileKind) -> &TargetConfig { + match kind { + CompileKind::Host => &self.host_config, + CompileKind::Target(s) => &self.target_config[&s], + } + } + + pub fn get_unsupported_std_targets(&self) -> Vec<&str> { + let mut unsupported = Vec::new(); + for (target, target_info) in &self.target_info { + if target_info.supports_std == Some(false) { + unsupported.push(target.short_name()); + } + } + unsupported + } +} + +/// Structure used to deal with Rustdoc fingerprinting +#[derive(Debug, Serialize, Deserialize)] +pub struct RustDocFingerprint { + pub rustc_vv: String, +} + +impl RustDocFingerprint { + /// This function checks whether the latest version of `Rustc` used to compile this + /// `Workspace`'s docs was the same as the one is currently being used in this `cargo doc` + /// call. + /// + /// In case it's not, it takes care of removing the `doc/` folder as well as overwriting + /// the rustdoc fingerprint info in order to guarantee that we won't end up with mixed + /// versions of the `js/html/css` files that `rustdoc` autogenerates which do not have + /// any versioning. + pub fn check_rustdoc_fingerprint(build_runner: &BuildRunner<'_, '_>) -> CargoResult<()> { + if build_runner + .bcx + .gctx + .cli_unstable() + .skip_rustdoc_fingerprint + { + return Ok(()); + } + let actual_rustdoc_target_data = RustDocFingerprint { + rustc_vv: build_runner.bcx.rustc().verbose_version.clone(), + }; + + let fingerprint_path = build_runner + .files() + .host_root() + .join(".rustdoc_fingerprint.json"); + let write_fingerprint = || -> CargoResult<()> { + paths::write( + &fingerprint_path, + serde_json::to_string(&actual_rustdoc_target_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 bootstrap were creating the doc directory before running + // `cargo doc` in a way that deleting it would break it. + return write_fingerprint(); + }; + match serde_json::from_str::(&rustdoc_data) { + Ok(fingerprint) => { + if fingerprint.rustc_vv == actual_rustdoc_target_data.rustc_vv { + return Ok(()); + } else { + tracing::debug!( + "doc fingerprint changed:\noriginal:\n{}\nnew:\n{}", + fingerprint.rustc_vv, + actual_rustdoc_target_data.rustc_vv + ); + } + } + Err(e) => { + tracing::debug!("could not deserialize {:?}: {}", fingerprint_path, e); + } + }; + // Fingerprint does not match, delete the doc directories and write a new fingerprint. + tracing::debug!( + "fingerprint {:?} mismatch, clearing doc directories", + fingerprint_path + ); + build_runner + .bcx + .all_kinds + .iter() + .map(|kind| build_runner.files().layout(*kind).doc()) + .filter(|path| path.exists()) + .try_for_each(|path| clean_doc(path))?; + write_fingerprint()?; + return Ok(()); + + fn clean_doc(path: &Path) -> CargoResult<()> { + let entries = path + .read_dir() + .with_context(|| format!("failed to read directory `{}`", path.display()))?; + for entry in entries { + let entry = entry?; + // Don't remove hidden files. Rustdoc does not create them, + // but the user might have. + if entry + .file_name() + .to_str() + .map_or(false, |name| name.starts_with('.')) + { + continue; + } + let path = entry.path(); + if entry.file_type()?.is_dir() { + paths::remove_dir_all(path)?; + } else { + paths::remove_file(path)?; + } + } + Ok(()) + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_plan.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_plan.rs new file mode 100644 index 000000000..ad3e65625 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_plan.rs @@ -0,0 +1,160 @@ +//! A graph-like structure used to represent the rustc commands to build the package and the +//! interdependencies between them. +//! +//! The `BuildPlan` structure is used to store the dependency graph of a dry run so that it can be +//! shared with an external build system. Each Invocation in the `BuildPlan` comprises a single +//! subprocess and defines the build environment, the outputs produced by the subprocess, and the +//! dependencies on other Invocations. + +use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; + +use serde::Serialize; + +use super::build_runner::OutputFile; +use super::{BuildRunner, CompileKind, CompileMode, Unit}; +use crate::core::TargetKind; +use crate::util::{internal, CargoResult, GlobalContext}; +use cargo_util::ProcessBuilder; + +#[derive(Debug, Serialize)] +struct Invocation { + package_name: String, + package_version: semver::Version, + target_kind: TargetKind, + kind: CompileKind, + compile_mode: CompileMode, + deps: Vec, + outputs: Vec, + links: BTreeMap, + program: String, + args: Vec, + env: BTreeMap, + cwd: Option, +} + +#[derive(Debug)] +pub struct BuildPlan { + invocation_map: BTreeMap, + plan: SerializedBuildPlan, +} + +#[derive(Debug, Serialize)] +struct SerializedBuildPlan { + invocations: Vec, + inputs: Vec, +} + +impl Invocation { + pub fn new(unit: &Unit, deps: Vec) -> Invocation { + let id = unit.pkg.package_id(); + Invocation { + package_name: id.name().to_string(), + package_version: id.version().clone(), + kind: unit.kind, + target_kind: unit.target.kind().clone(), + compile_mode: unit.mode, + deps, + outputs: Vec::new(), + links: BTreeMap::new(), + program: String::new(), + args: Vec::new(), + env: BTreeMap::new(), + cwd: None, + } + } + + pub fn add_output(&mut self, path: &Path, link: &Option) { + self.outputs.push(path.to_path_buf()); + if let Some(ref link) = *link { + self.links.insert(link.clone(), path.to_path_buf()); + } + } + + pub fn update_cmd(&mut self, cmd: &ProcessBuilder) -> CargoResult<()> { + self.program = cmd + .get_program() + .to_str() + .ok_or_else(|| anyhow::format_err!("unicode program string required"))? + .to_string(); + self.cwd = Some(cmd.get_cwd().unwrap().to_path_buf()); + for arg in cmd.get_args() { + self.args.push( + arg.to_str() + .ok_or_else(|| anyhow::format_err!("unicode argument string required"))? + .to_string(), + ); + } + for (var, value) in cmd.get_envs() { + let Some(value) = value else { continue }; + self.env.insert( + var.clone(), + value + .to_str() + .ok_or_else(|| anyhow::format_err!("unicode environment value required"))? + .to_string(), + ); + } + Ok(()) + } +} + +impl BuildPlan { + pub fn new() -> BuildPlan { + BuildPlan { + invocation_map: BTreeMap::new(), + plan: SerializedBuildPlan::new(), + } + } + + pub fn add(&mut self, build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<()> { + let id = self.plan.invocations.len(); + self.invocation_map.insert(unit.buildkey(), id); + let deps = build_runner + .unit_deps(unit) + .iter() + .map(|dep| self.invocation_map[&dep.unit.buildkey()]) + .collect(); + let invocation = Invocation::new(unit, deps); + self.plan.invocations.push(invocation); + Ok(()) + } + + pub fn update( + &mut self, + invocation_name: &str, + cmd: &ProcessBuilder, + outputs: &[OutputFile], + ) -> CargoResult<()> { + let id = self.invocation_map[invocation_name]; + let invocation = + self.plan.invocations.get_mut(id).ok_or_else(|| { + internal(format!("couldn't find invocation for {}", invocation_name)) + })?; + + invocation.update_cmd(cmd)?; + for output in outputs.iter() { + invocation.add_output(&output.path, &output.hardlink); + } + + Ok(()) + } + + pub fn set_inputs(&mut self, inputs: Vec) { + self.plan.inputs = inputs; + } + + pub fn output_plan(self, gctx: &GlobalContext) { + let encoded = serde_json::to_string(&self.plan).unwrap(); + crate::drop_println!(gctx, "{}", encoded); + } +} + +impl SerializedBuildPlan { + pub fn new() -> SerializedBuildPlan { + SerializedBuildPlan { + invocations: Vec::new(), + inputs: Vec::new(), + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/compilation_files.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/compilation_files.rs new file mode 100644 index 000000000..8c7ddff7f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/compilation_files.rs @@ -0,0 +1,841 @@ +//! See [`CompilationFiles`]. + +use std::collections::HashMap; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use lazycell::LazyCell; +use tracing::debug; + +use super::{BuildContext, BuildRunner, CompileKind, FileFlavor, Layout}; +use crate::core::compiler::{CompileMode, CompileTarget, CrateType, FileType, Unit}; +use crate::core::{Target, TargetKind, Workspace}; +use crate::util::{self, CargoResult, StableHasher}; + +/// This is a generic version number that can be changed to make +/// backwards-incompatible changes to any file structures in the output +/// directory. For example, the fingerprint files or the build-script +/// output files. +/// +/// Normally cargo updates ship with rustc updates which will +/// cause a new hash due to the rustc version changing, but this allows +/// cargo to be extra careful to deal with different versions of cargo that +/// use the same rustc version. +const METADATA_VERSION: u8 = 2; + +/// Uniquely identify a [`Unit`] under specific circumstances, see [`Metadata`] for more. +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] +pub struct UnitHash(u64); + +impl fmt::Display for UnitHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:016x}", self.0) + } +} + +impl fmt::Debug for UnitHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "UnitHash({:016x})", self.0) + } +} + +/// [`Metadata`] tracks several [`UnitHash`]s, including +/// [`Metadata::unit_id`], [`Metadata::c_metadata`], and [`Metadata::c_extra_filename`]. +/// +/// We use a hash because it is an easy way to guarantee +/// that all the inputs can be converted to a valid path. +/// +/// [`Metadata::unit_id`] is used to uniquely identify a unit in the build graph. +/// This serves as a similar role as [`Metadata::c_extra_filename`] in that it uniquely identifies output +/// on the filesystem except that its always present. +/// +/// [`Metadata::c_extra_filename`] is needed for cases like: +/// - A project may depend on crate `A` and crate `B`, so the package name must be in the file name. +/// - Similarly a project may depend on two versions of `A`, so the version must be in the file name. +/// +/// This also acts as the main layer of caching provided by Cargo +/// so this must include all things that need to be distinguished in different parts of +/// the same build. This is absolutely required or we override things before +/// we get chance to use them. +/// +/// For example, we want to cache `cargo build` and `cargo doc` separately, so that running one +/// does not invalidate the artifacts for the other. We do this by including [`CompileMode`] in the +/// hash, thus the artifacts go in different folders and do not override each other. +/// If we don't add something that we should have, for this reason, we get the +/// correct output but rebuild more than is needed. +/// +/// Some things that need to be tracked to ensure the correct output should definitely *not* +/// go in the `Metadata`. For example, the modification time of a file, should be tracked to make a +/// rebuild when the file changes. However, it would be wasteful to include in the `Metadata`. The +/// old artifacts are never going to be needed again. We can save space by just overwriting them. +/// If we add something that we should not have, for this reason, we get the correct output but take +/// more space than needed. This makes not including something in `Metadata` +/// a form of cache invalidation. +/// +/// Note that the `Fingerprint` is in charge of tracking everything needed to determine if a +/// rebuild is needed. +/// +/// [`Metadata::c_metadata`] is used for symbol mangling, because if you have two versions of +/// the same crate linked together, their symbols need to be differentiated. +/// +/// You should avoid anything that would interfere with reproducible +/// builds. For example, *any* absolute path should be avoided. This is one +/// reason that `RUSTFLAGS` is not in [`Metadata::c_metadata`], because it often has +/// absolute paths (like `--remap-path-prefix` which is fundamentally used for +/// reproducible builds and has absolute paths in it). Also, in some cases the +/// mangled symbols need to be stable between different builds with different +/// settings. For example, profile-guided optimizations need to swap +/// `RUSTFLAGS` between runs, but needs to keep the same symbol names. +#[derive(Copy, Clone, Debug)] +pub struct Metadata { + unit_id: UnitHash, + c_metadata: UnitHash, + c_extra_filename: Option, +} + +impl Metadata { + /// A hash to identify a given [`Unit`] in the build graph + pub fn unit_id(&self) -> UnitHash { + self.unit_id + } + + /// A hash to add to symbol naming through `-C metadata` + pub fn c_metadata(&self) -> UnitHash { + self.c_metadata + } + + /// A hash to add to file names through `-C extra-filename` + pub fn c_extra_filename(&self) -> Option { + self.c_extra_filename + } +} + +/// Collection of information about the files emitted by the compiler, and the +/// output directory structure. +pub struct CompilationFiles<'a, 'gctx> { + /// The target directory layout for the host (and target if it is the same as host). + pub(super) host: Layout, + /// The target directory layout for the target (if different from then host). + pub(super) target: HashMap, + /// Additional directory to include a copy of the outputs. + export_dir: Option, + /// The root targets requested by the user on the command line (does not + /// include dependencies). + roots: Vec, + ws: &'a Workspace<'gctx>, + /// Metadata hash to use for each unit. + metas: HashMap, + /// For each Unit, a list all files produced. + outputs: HashMap>>>, +} + +/// Info about a single file emitted by the compiler. +#[derive(Debug)] +pub struct OutputFile { + /// Absolute path to the file that will be produced by the build process. + pub path: PathBuf, + /// If it should be linked into `target`, and what it should be called + /// (e.g., without metadata). + pub hardlink: Option, + /// 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, +} + +impl OutputFile { + /// Gets the hard link if present; otherwise, returns the path. + pub fn bin_dst(&self) -> &PathBuf { + match self.hardlink { + Some(ref link_dst) => link_dst, + None => &self.path, + } + } +} + +impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { + pub(super) fn new( + build_runner: &BuildRunner<'a, 'gctx>, + host: Layout, + target: HashMap, + ) -> CompilationFiles<'a, 'gctx> { + let mut metas = HashMap::new(); + for unit in &build_runner.bcx.roots { + metadata_of(unit, build_runner, &mut metas); + } + let outputs = metas + .keys() + .cloned() + .map(|unit| (unit, LazyCell::new())) + .collect(); + CompilationFiles { + ws: build_runner.bcx.ws, + host, + target, + export_dir: build_runner.bcx.build_config.export_dir.clone(), + roots: build_runner.bcx.roots.clone(), + metas, + outputs, + } + } + + /// Returns the appropriate directory layout for either a plugin or not. + pub fn layout(&self, kind: CompileKind) -> &Layout { + match kind { + CompileKind::Host => &self.host, + CompileKind::Target(target) => &self.target[&target], + } + } + + /// Gets the metadata for the given unit. + /// + /// See [`Metadata`] and [`fingerprint`] module for more. + /// + /// [`fingerprint`]: super::super::fingerprint#fingerprints-and-metadata + pub fn metadata(&self, unit: &Unit) -> Metadata { + self.metas[unit] + } + + /// Gets the short hash based only on the `PackageId`. + /// Used for the metadata when `metadata` returns `None`. + pub fn target_short_hash(&self, unit: &Unit) -> String { + let hashable = unit.pkg.package_id().stable_hash(self.ws.root()); + util::short_hash(&(METADATA_VERSION, hashable)) + } + + /// Returns the directory where the artifacts for the given unit are + /// initially created. + pub fn out_dir(&self, unit: &Unit) -> PathBuf { + // Docscrape units need to have doc/ set as the out_dir so sources for reverse-dependencies + // will be put into doc/ and not into deps/ where the *.examples files are stored. + if unit.mode.is_doc() || unit.mode.is_doc_scrape() { + self.layout(unit.kind).doc().to_path_buf() + } else if unit.mode.is_doc_test() { + panic!("doc tests do not have an out dir"); + } else if unit.target.is_custom_build() { + self.build_script_dir(unit) + } else if unit.target.is_example() { + self.layout(unit.kind).examples().to_path_buf() + } else if unit.artifact.is_true() { + self.artifact_dir(unit) + } else { + self.deps_dir(unit).to_path_buf() + } + } + + /// Additional export directory from `--artifact-dir`. + pub fn export_dir(&self) -> Option { + self.export_dir.clone() + } + + /// Directory name to use for a package in the form `NAME-HASH`. + /// + /// Note that some units may share the same directory, so care should be + /// taken in those cases! + fn pkg_dir(&self, unit: &Unit) -> String { + let name = unit.pkg.package_id().name(); + let meta = self.metas[unit]; + if let Some(c_extra_filename) = meta.c_extra_filename() { + format!("{}-{}", name, c_extra_filename) + } else { + format!("{}-{}", name, self.target_short_hash(unit)) + } + } + + /// Returns the final artifact path for the host (`/…/target/debug`) + pub fn host_dest(&self) -> &Path { + self.host.dest() + } + + /// Returns the root of the build output tree for the host (`/…/target`) + pub fn host_root(&self) -> &Path { + self.host.root() + } + + /// Returns the host `deps` directory path. + pub fn host_deps(&self) -> &Path { + self.host.deps() + } + + /// Returns the directories where Rust crate dependencies are found for the + /// specified unit. + pub fn deps_dir(&self, unit: &Unit) -> &Path { + self.layout(unit.kind).deps() + } + + /// Directory where the fingerprint for the given unit should go. + pub fn fingerprint_dir(&self, unit: &Unit) -> PathBuf { + let dir = self.pkg_dir(unit); + self.layout(unit.kind).fingerprint().join(dir) + } + + /// Returns the path for a file in the fingerprint directory. + /// + /// The "prefix" should be something to distinguish the file from other + /// files in the fingerprint directory. + pub fn fingerprint_file_path(&self, unit: &Unit, prefix: &str) -> PathBuf { + // Different targets need to be distinguished in the + let kind = unit.target.kind().description(); + let flavor = if unit.mode.is_any_test() { + "test-" + } else if unit.mode.is_doc() { + "doc-" + } else if unit.mode.is_run_custom_build() { + "run-" + } else { + "" + }; + let name = format!("{}{}{}-{}", prefix, flavor, kind, unit.target.name()); + self.fingerprint_dir(unit).join(name) + } + + /// Path where compiler output is cached. + pub fn message_cache_path(&self, unit: &Unit) -> PathBuf { + self.fingerprint_file_path(unit, "output-") + } + + /// Returns the directory where a compiled build script is stored. + /// `/path/to/target/{debug,release}/build/PKG-HASH` + pub fn build_script_dir(&self, unit: &Unit) -> PathBuf { + assert!(unit.target.is_custom_build()); + assert!(!unit.mode.is_run_custom_build()); + assert!(self.metas.contains_key(unit)); + let dir = self.pkg_dir(unit); + self.layout(CompileKind::Host).build().join(dir) + } + + /// Returns the directory for compiled artifacts files. + /// `/path/to/target/{debug,release}/deps/artifact/KIND/PKG-HASH` + fn artifact_dir(&self, unit: &Unit) -> PathBuf { + assert!(self.metas.contains_key(unit)); + assert!(unit.artifact.is_true()); + let dir = self.pkg_dir(unit); + let kind = match unit.target.kind() { + TargetKind::Bin => "bin", + TargetKind::Lib(lib_kinds) => match lib_kinds.as_slice() { + &[CrateType::Cdylib] => "cdylib", + &[CrateType::Staticlib] => "staticlib", + invalid => unreachable!( + "BUG: unexpected artifact library type(s): {:?} - these should have been split", + invalid + ), + }, + invalid => unreachable!( + "BUG: {:?} are not supposed to be used as artifacts", + invalid + ), + }; + self.layout(unit.kind).artifact().join(dir).join(kind) + } + + /// Returns the directory where information about running a build script + /// is stored. + /// `/path/to/target/{debug,release}/build/PKG-HASH` + pub fn build_script_run_dir(&self, unit: &Unit) -> PathBuf { + assert!(unit.target.is_custom_build()); + assert!(unit.mode.is_run_custom_build()); + let dir = self.pkg_dir(unit); + self.layout(unit.kind).build().join(dir) + } + + /// Returns the "`OUT_DIR`" directory for running a build script. + /// `/path/to/target/{debug,release}/build/PKG-HASH/out` + pub fn build_script_out_dir(&self, unit: &Unit) -> PathBuf { + self.build_script_run_dir(unit).join("out") + } + + /// Returns the path to the executable binary for the given bin target. + /// + /// This should only to be used when a `Unit` is not available. + pub fn bin_link_for_target( + &self, + target: &Target, + kind: CompileKind, + bcx: &BuildContext<'_, '_>, + ) -> CargoResult { + assert!(target.is_bin()); + let dest = self.layout(kind).dest(); + let info = bcx.target_data.info(kind); + let (file_types, _) = info + .rustc_outputs( + CompileMode::Build, + &TargetKind::Bin, + bcx.target_data.short_name(&kind), + ) + .expect("target must support `bin`"); + + let file_type = file_types + .iter() + .find(|file_type| file_type.flavor == FileFlavor::Normal) + .expect("target must support `bin`"); + + Ok(dest.join(file_type.uplift_filename(target))) + } + + /// Returns the filenames that the given unit will generate. + /// + /// Note: It is not guaranteed that all of the files will be generated. + pub(super) fn outputs( + &self, + unit: &Unit, + bcx: &BuildContext<'a, 'gctx>, + ) -> CargoResult>> { + self.outputs[unit] + .try_borrow_with(|| self.calc_outputs(unit, bcx)) + .map(Arc::clone) + } + + /// Returns the path where the output for the given unit and `FileType` + /// should be uplifted to. + /// + /// Returns `None` if the unit shouldn't be uplifted (for example, a + /// dependent rlib). + fn uplift_to(&self, unit: &Unit, file_type: &FileType, from_path: &Path) -> Option { + // Tests, check, doc, etc. should not be uplifted. + if unit.mode != CompileMode::Build || file_type.flavor == FileFlavor::Rmeta { + return None; + } + + // Artifact dependencies are never uplifted. + if unit.artifact.is_true() { + return None; + } + + // - Binaries: The user always wants to see these, even if they are + // implicitly built (for example for integration tests). + // - dylibs: This ensures that the dynamic linker pulls in all the + // latest copies (even if the dylib was built from a previous cargo + // build). There are complex reasons for this, see #8139, #6167, #6162. + // - Things directly requested from the command-line (the "roots"). + // This one is a little questionable for rlibs (see #6131), but is + // historically how Cargo has operated. This is primarily useful to + // give the user access to staticlibs and cdylibs. + if !unit.target.is_bin() + && !unit.target.is_custom_build() + && file_type.crate_type != Some(CrateType::Dylib) + && !self.roots.contains(unit) + { + return None; + } + + let filename = file_type.uplift_filename(&unit.target); + let uplift_path = if unit.target.is_example() { + // Examples live in their own little world. + self.layout(unit.kind).examples().join(filename) + } else if unit.target.is_custom_build() { + self.build_script_dir(unit).join(filename) + } else { + self.layout(unit.kind).dest().join(filename) + }; + if from_path == uplift_path { + // This can happen with things like examples that reside in the + // same directory, do not have a metadata hash (like on Windows), + // and do not have hyphens. + return None; + } + Some(uplift_path) + } + + /// Calculates the filenames that the given unit will generate. + /// Should use [`CompilationFiles::outputs`] instead + /// as it caches the result of this function. + fn calc_outputs( + &self, + unit: &Unit, + bcx: &BuildContext<'a, 'gctx>, + ) -> CargoResult>> { + let ret = match unit.mode { + CompileMode::Doc { json, .. } => { + let path = if json { + self.out_dir(unit) + .join(format!("{}.json", unit.target.crate_name())) + } else { + self.out_dir(unit) + .join(unit.target.crate_name()) + .join("index.html") + }; + + vec![OutputFile { + path, + hardlink: None, + export_path: None, + flavor: FileFlavor::Normal, + }] + } + CompileMode::RunCustomBuild => { + // At this time, this code path does not handle build script + // outputs. + vec![] + } + CompileMode::Doctest => { + // Doctests are built in a temporary directory and then + // deleted. There is the `--persist-doctests` unstable flag, + // but Cargo does not know about that. + vec![] + } + CompileMode::Docscrape => { + // The file name needs to be stable across Cargo sessions. + // This originally used unit.buildkey(), but that isn't stable, + // so we use metadata instead (prefixed with name for debugging). + let file_name = format!( + "{}-{}.examples", + unit.pkg.name(), + self.metadata(unit).unit_id() + ); + let path = self.deps_dir(unit).join(file_name); + vec![OutputFile { + path, + hardlink: None, + export_path: None, + flavor: FileFlavor::Normal, + }] + } + CompileMode::Test + | CompileMode::Build + | CompileMode::Bench + | CompileMode::Check { .. } => self.calc_outputs_rustc(unit, bcx)?, + }; + debug!("Target filenames: {:?}", ret); + + Ok(Arc::new(ret)) + } + + /// Computes the actual, full pathnames for all the files generated by rustc. + /// + /// The `OutputFile` also contains the paths where those files should be + /// "uplifted" to. + fn calc_outputs_rustc( + &self, + unit: &Unit, + bcx: &BuildContext<'a, 'gctx>, + ) -> CargoResult> { + let out_dir = self.out_dir(unit); + + let info = bcx.target_data.info(unit.kind); + let triple = bcx.target_data.short_name(&unit.kind); + let (file_types, unsupported) = + info.rustc_outputs(unit.mode, unit.target.kind(), triple)?; + if file_types.is_empty() { + if !unsupported.is_empty() { + let unsupported_strs: Vec<_> = unsupported.iter().map(|ct| ct.as_str()).collect(); + anyhow::bail!( + "cannot produce {} for `{}` as the target `{}` \ + does not support these crate types", + unsupported_strs.join(", "), + unit.pkg, + triple, + ) + } + anyhow::bail!( + "cannot compile `{}` as the target `{}` does not \ + support any of the output crate types", + unit.pkg, + triple, + ); + } + + // Convert FileType to OutputFile. + let mut outputs = Vec::new(); + for file_type in file_types { + let meta = self.metas[unit]; + let meta_opt = meta.c_extra_filename().map(|h| h.to_string()); + let path = out_dir.join(file_type.output_filename(&unit.target, meta_opt.as_deref())); + + // If, the `different_binary_name` feature is enabled, the name of the hardlink will + // be the name of the binary provided by the user in `Cargo.toml`. + let hardlink = self.uplift_to(unit, &file_type, &path); + let export_path = if unit.target.is_custom_build() { + None + } else { + self.export_dir.as_ref().and_then(|export_dir| { + hardlink + .as_ref() + .map(|hardlink| export_dir.join(hardlink.file_name().unwrap())) + }) + }; + outputs.push(OutputFile { + path, + hardlink, + export_path, + flavor: file_type.flavor, + }); + } + Ok(outputs) + } +} + +/// Gets the metadata hash 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>( + unit: &Unit, + build_runner: &BuildRunner<'_, '_>, + metas: &'a mut HashMap, +) -> &'a Metadata { + if !metas.contains_key(unit) { + let meta = compute_metadata(unit, build_runner, metas); + metas.insert(unit.clone(), meta); + for dep in build_runner.unit_deps(unit) { + metadata_of(&dep.unit, build_runner, metas); + } + } + &metas[unit] +} + +/// Computes the metadata hash for the given [`Unit`]. +fn compute_metadata( + unit: &Unit, + build_runner: &BuildRunner<'_, '_>, + metas: &mut HashMap, +) -> Metadata { + let bcx = &build_runner.bcx; + let deps_metadata = build_runner + .unit_deps(unit) + .iter() + .map(|dep| *metadata_of(&dep.unit, build_runner, metas)) + .collect::>(); + let use_extra_filename = use_extra_filename(bcx, unit); + + let mut shared_hasher = StableHasher::new(); + + METADATA_VERSION.hash(&mut shared_hasher); + + let ws_root = if unit.is_std { + // SourceId for stdlib crates is an absolute path inside the sysroot. + // Pass the sysroot as workspace root so that we hash a relative path. + // This avoids the metadata hash changing depending on where the user installed rustc. + &bcx.target_data.get_info(unit.kind).unwrap().sysroot + } else { + bcx.ws.root() + }; + + // Unique metadata per (name, source, version) triple. This'll allow us + // to pull crates from anywhere without worrying about conflicts. + unit.pkg + .package_id() + .stable_hash(ws_root) + .hash(&mut shared_hasher); + + // Also mix in enabled features to our metadata. This'll ensure that + // when changing feature sets each lib is separately cached. + unit.features.hash(&mut shared_hasher); + + // Throw in the profile we're compiling with. This helps caching + // `panic=abort` and `panic=unwind` artifacts, additionally with various + // settings like debuginfo and whatnot. + unit.profile.hash(&mut shared_hasher); + unit.mode.hash(&mut shared_hasher); + build_runner.lto[unit].hash(&mut shared_hasher); + + // Artifacts compiled for the host should have a different + // metadata piece than those compiled for the target, so make sure + // we throw in the unit's `kind` as well. Use `fingerprint_hash` + // so that the StableHash doesn't change based on the pathnames + // of the custom target JSON spec files. + unit.kind.fingerprint_hash().hash(&mut shared_hasher); + + // Finally throw in the target name/kind. This ensures that concurrent + // compiles of targets in the same crate don't collide. + unit.target.name().hash(&mut shared_hasher); + unit.target.kind().hash(&mut shared_hasher); + + hash_rustc_version(bcx, &mut shared_hasher, unit); + + if build_runner.bcx.ws.is_member(&unit.pkg) { + // This is primarily here for clippy. This ensures that the clippy + // artifacts are separate from the `check` ones. + if let Some(path) = &build_runner.bcx.rustc().workspace_wrapper { + path.hash(&mut shared_hasher); + } + } + + // Seed the contents of `__CARGO_DEFAULT_LIB_METADATA` to the hasher if present. + // This should be the release channel, to get a different hash for each channel. + if let Ok(ref channel) = build_runner + .bcx + .gctx + .get_env("__CARGO_DEFAULT_LIB_METADATA") + { + channel.hash(&mut shared_hasher); + } + + // std units need to be kept separate from user dependencies. std crates + // are differentiated in the Unit with `is_std` (for things like + // `-Zforce-unstable-if-unmarked`), so they are always built separately. + // This isn't strictly necessary for build dependencies which probably + // don't need unstable support. A future experiment might be to set + // `is_std` to false for build dependencies so that they can be shared + // with user dependencies. + unit.is_std.hash(&mut shared_hasher); + + // While we don't hash RUSTFLAGS because it may contain absolute paths that + // hurts reproducibility, we track whether a unit's RUSTFLAGS is from host + // config, so that we can generate a different metadata hash for runtime + // and compile-time units. + // + // HACK: This is a temporary hack for fixing rust-lang/cargo#14253 + // Need to find a long-term solution to replace this fragile workaround. + // See https://github.com/rust-lang/cargo/pull/14432#discussion_r1725065350 + if unit.kind.is_host() && !bcx.gctx.target_applies_to_host().unwrap_or_default() { + let host_info = bcx.target_data.info(CompileKind::Host); + let target_configs_are_different = unit.rustflags != host_info.rustflags + || unit.rustdocflags != host_info.rustdocflags + || bcx + .target_data + .target_config(CompileKind::Host) + .links_overrides + != unit.links_overrides; + target_configs_are_different.hash(&mut shared_hasher); + } + + let mut c_metadata_hasher = shared_hasher.clone(); + // Mix in the target-metadata of all the dependencies of this target. + let mut dep_c_metadata_hashes = deps_metadata + .iter() + .map(|m| m.c_metadata) + .collect::>(); + dep_c_metadata_hashes.sort(); + dep_c_metadata_hashes.hash(&mut c_metadata_hasher); + + let mut c_extra_filename_hasher = shared_hasher.clone(); + // Mix in the target-metadata of all the dependencies of this target. + let mut dep_c_extra_filename_hashes = deps_metadata + .iter() + .map(|m| m.c_extra_filename) + .collect::>(); + dep_c_extra_filename_hashes.sort(); + dep_c_extra_filename_hashes.hash(&mut c_extra_filename_hasher); + // Avoid trashing the caches on RUSTFLAGS changing via `c_extra_filename` + // + // Limited to `c_extra_filename` to help with reproducible build / PGO issues. + let default = Vec::new(); + let extra_args = build_runner.bcx.extra_args_for(unit).unwrap_or(&default); + if !has_remap_path_prefix(&extra_args) { + extra_args.hash(&mut c_extra_filename_hasher); + } + if unit.mode.is_doc() || unit.mode.is_doc_scrape() { + if !has_remap_path_prefix(&unit.rustdocflags) { + unit.rustdocflags.hash(&mut c_extra_filename_hasher); + } + } else { + if !has_remap_path_prefix(&unit.rustflags) { + unit.rustflags.hash(&mut c_extra_filename_hasher); + } + } + + let c_metadata = UnitHash(Hasher::finish(&c_metadata_hasher)); + let c_extra_filename = UnitHash(Hasher::finish(&c_extra_filename_hasher)); + let unit_id = c_extra_filename; + + let c_extra_filename = use_extra_filename.then_some(c_extra_filename); + + Metadata { + unit_id, + c_metadata, + c_extra_filename, + } +} + +/// HACK: Detect the *potential* presence of `--remap-path-prefix` +/// +/// As CLI parsing is contextual and dependent on the CLI definition to understand the context, we +/// can't say for sure whether `--remap-path-prefix` is present, so we guess if anything looks like +/// it. +/// If we could, we'd strip it out for hashing. +/// Instead, we use this to avoid hashing rustflags if it might be present to avoid the risk of taking +/// a flag that is trying to make things reproducible and making things less reproducible by the +/// `-Cextra-filename` showing up in the rlib, even with `split-debuginfo`. +fn has_remap_path_prefix(args: &[String]) -> bool { + args.iter() + .any(|s| s.starts_with("--remap-path-prefix=") || s == "--remap-path-prefix") +} + +/// Hash the version of rustc being used during the build process. +fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher, unit: &Unit) { + let vers = &bcx.rustc().version; + if vers.pre.is_empty() || bcx.gctx.cli_unstable().separate_nightlies { + // For stable, keep the artifacts separate. This helps if someone is + // testing multiple versions, to avoid recompiles. Note though that for + // cross-compiled builds the `host:` line of `verbose_version` is + // omitted since rustc should produce the same output for each target + // regardless of the host. + for line in bcx.rustc().verbose_version.lines() { + if unit.kind.is_host() || !line.starts_with("host: ") { + line.hash(hasher); + } + } + return; + } + // On "nightly"/"beta"/"dev"/etc, keep each "channel" separate. Don't hash + // the date/git information, so that whenever someone updates "nightly", + // they won't have a bunch of stale artifacts in the target directory. + // + // This assumes that the first segment is the important bit ("nightly", + // "beta", "dev", etc.). Skip other parts like the `.3` in `-beta.3`. + vers.pre.split('.').next().hash(hasher); + // Keep "host" since some people switch hosts to implicitly change + // targets, (like gnu vs musl or gnu vs msvc). In the future, we may want + // to consider hashing `unit.kind.short_name()` instead. + if unit.kind.is_host() { + bcx.rustc().host.hash(hasher); + } + // None of the other lines are important. Currently they are: + // binary: rustc <-- or "rustdoc" + // commit-hash: 38114ff16e7856f98b2b4be7ab4cd29b38bed59a + // commit-date: 2020-03-21 + // host: x86_64-apple-darwin + // release: 1.44.0-nightly + // LLVM version: 9.0 + // + // The backend version ("LLVM version") might become more relevant in + // the future when cranelift sees more use, and people want to switch + // between different backends without recompiling. +} + +/// Returns whether or not this unit should use a hash in the filename to make it unique. +fn use_extra_filename(bcx: &BuildContext<'_, '_>, unit: &Unit) -> bool { + if unit.mode.is_doc_test() || unit.mode.is_doc() { + // Doc tests do not have metadata. + return false; + } + if unit.mode.is_any_test() || unit.mode.is_check() { + // These always use metadata. + return true; + } + // No metadata in these cases: + // + // - dylibs: + // - if any dylib names are encoded in executables, so they can't be renamed. + // - TODO: Maybe use `-install-name` on macOS or `-soname` on other UNIX systems + // to specify the dylib name to be used by the linker instead of the filename. + // - Windows MSVC executables: The path to the PDB is embedded in the + // executable, and we don't want the PDB path to include the hash in it. + // - wasm32-unknown-emscripten executables: When using emscripten, the path to the + // .wasm file is embedded in the .js file, so we don't want the hash in there. + // + // This is only done for local packages, as we don't expect to export + // dependencies. + // + // The __CARGO_DEFAULT_LIB_METADATA env var is used to override this to + // force metadata in the hash. This is only used for building libstd. For + // example, if libstd is placed in a common location, we don't want a file + // named /usr/lib/libstd.so which could conflict with other rustc + // installs. In addition it prevents accidentally loading a libstd of a + // different compiler at runtime. + // See https://github.com/rust-lang/cargo/issues/3005 + let short_name = bcx.target_data.short_name(&unit.kind); + if (unit.target.is_dylib() + || unit.target.is_cdylib() + || (unit.target.is_executable() && short_name == "wasm32-unknown-emscripten") + || (unit.target.is_executable() && short_name.contains("msvc"))) + && unit.pkg.package_id().source_id().is_path() + && bcx.gctx.get_env("__CARGO_DEFAULT_LIB_METADATA").is_err() + { + return false; + } + true +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/mod.rs new file mode 100644 index 000000000..1a55d2110 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/build_runner/mod.rs @@ -0,0 +1,687 @@ +//! [`BuildRunner`] is the mutable state used during the build process. + +use std::collections::{BTreeSet, HashMap, HashSet}; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; + +use crate::core::compiler::compilation::{self, UnitOutput}; +use crate::core::compiler::{self, artifact, Unit}; +use crate::core::PackageId; +use crate::util::cache_lock::CacheLockMode; +use crate::util::errors::CargoResult; +use anyhow::{bail, Context as _}; +use filetime::FileTime; +use itertools::Itertools; +use jobserver::Client; + +use super::build_plan::BuildPlan; +use super::custom_build::{self, BuildDeps, BuildScriptOutputs, BuildScripts}; +use super::fingerprint::{Checksum, Fingerprint}; +use super::job_queue::JobQueue; +use super::layout::Layout; +use super::lto::Lto; +use super::unit_graph::UnitDep; +use super::{ + BuildContext, Compilation, CompileKind, CompileMode, Executor, FileFlavor, RustDocFingerprint, +}; + +mod compilation_files; +use self::compilation_files::CompilationFiles; +pub use self::compilation_files::{Metadata, OutputFile, UnitHash}; + +/// Collection of all the stuff that is needed to perform a build. +/// +/// Different from the [`BuildContext`], `Context` is a _mutable_ state used +/// throughout the entire build process. Everything is coordinated through this. +/// +/// [`BuildContext`]: crate::core::compiler::BuildContext +pub struct BuildRunner<'a, 'gctx> { + /// Mostly static information about the build task. + pub bcx: &'a BuildContext<'a, 'gctx>, + /// A large collection of information about the result of the entire compilation. + pub compilation: Compilation<'gctx>, + /// Output from build scripts, updated after each build script runs. + pub build_script_outputs: Arc>, + /// Dependencies (like rerun-if-changed) declared by a build script. + /// This is *only* populated from the output from previous runs. + /// If the build script hasn't ever been run, then it must be run. + pub build_explicit_deps: HashMap, + /// Fingerprints used to detect if a unit is out-of-date. + pub fingerprints: HashMap>, + /// Cache of file mtimes to reduce filesystem hits. + pub mtime_cache: HashMap, + /// Cache of file checksums to reduce filesystem reads. + pub checksum_cache: HashMap, + /// A set used to track which units have been compiled. + /// A unit may appear in the job graph multiple times as a dependency of + /// multiple packages, but it only needs to run once. + pub compiled: HashSet, + /// Linking information for each `Unit`. + /// See `build_map` for details. + pub build_scripts: HashMap>, + /// Job server client to manage concurrency with other processes. + pub jobserver: Client, + /// "Primary" packages are the ones the user selected on the command-line + /// with `-p` flags. If no flags are specified, then it is the defaults + /// based on the current directory and the default workspace members. + primary_packages: HashSet, + /// An abstraction of the files and directories that will be generated by + /// the compilation. This is `None` until after `unit_dependencies` has + /// been computed. + files: Option>, + + /// A set of units which are compiling rlibs and are expected to produce + /// metadata files in addition to the rlib itself. + rmeta_required: HashSet, + + /// Map of the LTO-status of each unit. This indicates what sort of + /// compilation is happening (only object, only bitcode, both, etc), and is + /// precalculated early on. + pub lto: HashMap, + + /// Map of Doc/Docscrape units to metadata for their -Cmetadata flag. + /// See `Context::find_metadata_units` for more details. + pub metadata_for_doc_units: HashMap, + + /// Set of metadata of Docscrape units that fail before completion, e.g. + /// because the target has a type error. This is in an Arc> + /// because it is continuously updated as the job progresses. + pub failed_scrape_units: Arc>>, +} + +impl<'a, 'gctx> BuildRunner<'a, 'gctx> { + pub fn new(bcx: &'a BuildContext<'a, 'gctx>) -> CargoResult { + // Load up the jobserver that we'll use to manage our parallelism. This + // is the same as the GNU make implementation of a jobserver, and + // intentionally so! It's hoped that we can interact with GNU make and + // all share the same jobserver. + // + // Note that if we don't have a jobserver in our environment then we + // create our own, and we create it with `n` tokens, but immediately + // acquire one, because one token is ourself, a running process. + let jobserver = match bcx.gctx.jobserver_from_env() { + Some(c) => c.clone(), + None => { + let client = + Client::new(bcx.jobs() as usize).context("failed to create jobserver")?; + client.acquire_raw()?; + client + } + }; + + Ok(Self { + bcx, + compilation: Compilation::new(bcx)?, + build_script_outputs: Arc::new(Mutex::new(BuildScriptOutputs::default())), + fingerprints: HashMap::new(), + mtime_cache: HashMap::new(), + checksum_cache: HashMap::new(), + compiled: HashSet::new(), + build_scripts: HashMap::new(), + build_explicit_deps: HashMap::new(), + jobserver, + primary_packages: HashSet::new(), + files: None, + rmeta_required: HashSet::new(), + lto: HashMap::new(), + metadata_for_doc_units: HashMap::new(), + failed_scrape_units: Arc::new(Mutex::new(HashSet::new())), + }) + } + + /// Dry-run the compilation without actually running it. + /// + /// This is expected to collect information like the location of output artifacts. + /// Please keep in sync with non-compilation part in [`BuildRunner::compile`]. + pub fn dry_run(mut self) -> CargoResult> { + let _lock = self + .bcx + .gctx + .acquire_package_cache_lock(CacheLockMode::Shared)?; + self.lto = super::lto::generate(self.bcx)?; + self.prepare_units()?; + self.prepare()?; + self.check_collisions()?; + + for unit in &self.bcx.roots { + self.collect_tests_and_executables(unit)?; + } + + Ok(self.compilation) + } + + /// Starts compilation, waits for it to finish, and returns information + /// about the result of compilation. + /// + /// See [`ops::cargo_compile`] for a higher-level view of the compile process. + /// + /// [`ops::cargo_compile`]: crate::ops::cargo_compile + #[tracing::instrument(skip_all)] + pub fn compile(mut self, exec: &Arc) -> CargoResult> { + // A shared lock is held during the duration of the build since rustc + // needs to read from the `src` cache, and we don't want other + // commands modifying the `src` cache while it is running. + let _lock = self + .bcx + .gctx + .acquire_package_cache_lock(CacheLockMode::Shared)?; + let mut queue = JobQueue::new(self.bcx); + let mut plan = BuildPlan::new(); + let build_plan = self.bcx.build_config.build_plan; + self.lto = super::lto::generate(self.bcx)?; + self.prepare_units()?; + self.prepare()?; + custom_build::build_map(&mut self)?; + self.check_collisions()?; + self.compute_metadata_for_doc_units(); + + // We need to make sure that if there were any previous docs + // already compiled, they were compiled with the same Rustc version that we're currently + // using. Otherwise we must remove the `doc/` folder and compile again forcing a rebuild. + // + // This is important because the `.js`/`.html` & `.css` files that are generated by Rustc don't have + // any versioning (See https://github.com/rust-lang/cargo/issues/8461). + // Therefore, we can end up with weird bugs and behaviours if we mix different + // versions of these files. + if self.bcx.build_config.mode.is_doc() { + RustDocFingerprint::check_rustdoc_fingerprint(&self)? + } + + for unit in &self.bcx.roots { + let force_rebuild = self.bcx.build_config.force_rebuild; + super::compile(&mut self, &mut queue, &mut plan, unit, exec, force_rebuild)?; + } + + // Now that we've got the full job queue and we've done all our + // fingerprint analysis to determine what to run, bust all the memoized + // fingerprint hashes to ensure that during the build they all get the + // most up-to-date values. In theory we only need to bust hashes that + // transitively depend on a dirty build script, but it shouldn't matter + // that much for performance anyway. + for fingerprint in self.fingerprints.values() { + fingerprint.clear_memoized(); + } + + // Now that we've figured out everything that we're going to do, do it! + queue.execute(&mut self, &mut plan)?; + + if build_plan { + plan.set_inputs(self.build_plan_inputs()?); + plan.output_plan(self.bcx.gctx); + } + + // Add `OUT_DIR` to env vars if unit has a build script. + let units_with_build_script = &self + .bcx + .roots + .iter() + .filter(|unit| self.build_scripts.contains_key(unit)) + .dedup_by(|x, y| x.pkg.package_id() == y.pkg.package_id()) + .collect::>(); + for unit in units_with_build_script { + for dep in &self.bcx.unit_graph[unit] { + if dep.unit.mode.is_run_custom_build() { + let out_dir = self + .files() + .build_script_out_dir(&dep.unit) + .display() + .to_string(); + let script_meta = self.get_run_build_script_metadata(&dep.unit); + self.compilation + .extra_env + .entry(script_meta) + .or_insert_with(Vec::new) + .push(("OUT_DIR".to_string(), out_dir)); + } + } + } + + // Collect the result of the build into `self.compilation`. + for unit in &self.bcx.roots { + self.collect_tests_and_executables(unit)?; + + // Collect information for `rustdoc --test`. + if unit.mode.is_doc_test() { + let mut unstable_opts = false; + let mut args = compiler::extern_args(&self, unit, &mut unstable_opts)?; + args.extend(compiler::lto_args(&self, unit)); + args.extend(compiler::features_args(unit)); + args.extend(compiler::check_cfg_args(unit)); + + let script_meta = self.find_build_script_metadata(unit); + if let Some(meta) = script_meta { + if let Some(output) = self.build_script_outputs.lock().unwrap().get(meta) { + for cfg in &output.cfgs { + args.push("--cfg".into()); + args.push(cfg.into()); + } + + for check_cfg in &output.check_cfgs { + args.push("--check-cfg".into()); + args.push(check_cfg.into()); + } + + for (lt, arg) in &output.linker_args { + if lt.applies_to(&unit.target) { + args.push("-C".into()); + args.push(format!("link-arg={}", arg).into()); + } + } + } + } + args.extend(unit.rustdocflags.iter().map(Into::into)); + + use super::MessageFormat; + let format = match self.bcx.build_config.message_format { + MessageFormat::Short => "short", + MessageFormat::Human => "human", + MessageFormat::Json { .. } => "json", + }; + args.push("--error-format".into()); + args.push(format.into()); + + self.compilation.to_doc_test.push(compilation::Doctest { + unit: unit.clone(), + args, + unstable_opts, + linker: self.compilation.target_linker(unit.kind).clone(), + script_meta, + env: artifact::get_env(&self, self.unit_deps(unit))?, + }); + } + + super::output_depinfo(&mut self, unit)?; + } + + for (script_meta, output) in self.build_script_outputs.lock().unwrap().iter() { + self.compilation + .extra_env + .entry(*script_meta) + .or_insert_with(Vec::new) + .extend(output.env.iter().cloned()); + + for dir in output.library_paths.iter() { + self.compilation.native_dirs.insert(dir.clone()); + } + } + Ok(self.compilation) + } + + fn collect_tests_and_executables(&mut self, unit: &Unit) -> CargoResult<()> { + for output in self.outputs(unit)?.iter() { + if output.flavor == FileFlavor::DebugInfo || output.flavor == FileFlavor::Auxiliary { + continue; + } + + let bindst = output.bin_dst(); + + if unit.mode == CompileMode::Test { + self.compilation + .tests + .push(self.unit_output(unit, &output.path)); + } else if unit.target.is_executable() { + self.compilation + .binaries + .push(self.unit_output(unit, bindst)); + } else if unit.target.is_cdylib() + && !self.compilation.cdylibs.iter().any(|uo| uo.unit == *unit) + { + self.compilation + .cdylibs + .push(self.unit_output(unit, bindst)); + } + } + Ok(()) + } + + /// Returns the executable for the specified unit (if any). + pub fn get_executable(&mut self, unit: &Unit) -> CargoResult> { + let is_binary = unit.target.is_executable(); + let is_test = unit.mode.is_any_test(); + if !unit.mode.generates_executable() || !(is_binary || is_test) { + return Ok(None); + } + Ok(self + .outputs(unit)? + .iter() + .find(|o| o.flavor == FileFlavor::Normal) + .map(|output| output.bin_dst().clone())) + } + + #[tracing::instrument(skip_all)] + pub fn prepare_units(&mut self) -> CargoResult<()> { + let dest = self.bcx.profiles.get_dir_name(); + let host_layout = Layout::new(self.bcx.ws, None, &dest)?; + let mut targets = HashMap::new(); + for kind in self.bcx.all_kinds.iter() { + if let CompileKind::Target(target) = *kind { + let layout = Layout::new(self.bcx.ws, Some(target), &dest)?; + targets.insert(target, layout); + } + } + self.primary_packages + .extend(self.bcx.roots.iter().map(|u| u.pkg.package_id())); + self.compilation + .root_crate_names + .extend(self.bcx.roots.iter().map(|u| u.target.crate_name())); + + self.record_units_requiring_metadata(); + + let files = CompilationFiles::new(self, host_layout, targets); + self.files = Some(files); + Ok(()) + } + + /// Prepare this context, ensuring that all filesystem directories are in + /// place. + #[tracing::instrument(skip_all)] + pub fn prepare(&mut self) -> CargoResult<()> { + self.files + .as_mut() + .unwrap() + .host + .prepare() + .context("couldn't prepare build directories")?; + for target in self.files.as_mut().unwrap().target.values_mut() { + target + .prepare() + .context("couldn't prepare build directories")?; + } + + let files = self.files.as_ref().unwrap(); + for &kind in self.bcx.all_kinds.iter() { + let layout = files.layout(kind); + self.compilation + .root_output + .insert(kind, layout.dest().to_path_buf()); + self.compilation + .deps_output + .insert(kind, layout.deps().to_path_buf()); + } + Ok(()) + } + + pub fn files(&self) -> &CompilationFiles<'a, 'gctx> { + self.files.as_ref().unwrap() + } + + /// Returns the filenames that the given unit will generate. + pub fn outputs(&self, unit: &Unit) -> CargoResult>> { + self.files.as_ref().unwrap().outputs(unit, self.bcx) + } + + /// Direct dependencies for the given unit. + pub fn unit_deps(&self, unit: &Unit) -> &[UnitDep] { + &self.bcx.unit_graph[unit] + } + + /// Returns the `RunCustomBuild` Unit associated with the given Unit. + /// + /// If the package does not have a build script, this returns None. + pub fn find_build_script_unit(&self, unit: &Unit) -> Option { + if unit.mode.is_run_custom_build() { + return Some(unit.clone()); + } + self.bcx.unit_graph[unit] + .iter() + .find(|unit_dep| { + unit_dep.unit.mode.is_run_custom_build() + && unit_dep.unit.pkg.package_id() == unit.pkg.package_id() + }) + .map(|unit_dep| unit_dep.unit.clone()) + } + + /// Returns the metadata hash for the `RunCustomBuild` Unit associated with + /// the given unit. + /// + /// If the package does not have a build script, this returns None. + pub fn find_build_script_metadata(&self, unit: &Unit) -> Option { + let script_unit = self.find_build_script_unit(unit)?; + Some(self.get_run_build_script_metadata(&script_unit)) + } + + /// Returns the metadata hash for a `RunCustomBuild` unit. + pub fn get_run_build_script_metadata(&self, unit: &Unit) -> UnitHash { + assert!(unit.mode.is_run_custom_build()); + self.files().metadata(unit).unit_id() + } + + pub fn is_primary_package(&self, unit: &Unit) -> bool { + self.primary_packages.contains(&unit.pkg.package_id()) + } + + /// Returns the list of filenames read by cargo to generate the [`BuildContext`] + /// (all `Cargo.toml`, etc.). + pub fn build_plan_inputs(&self) -> CargoResult> { + // Keep sorted for consistency. + let mut inputs = BTreeSet::new(); + // Note: dev-deps are skipped if they are not present in the unit graph. + for unit in self.bcx.unit_graph.keys() { + inputs.insert(unit.pkg.manifest_path().to_path_buf()); + } + Ok(inputs.into_iter().collect()) + } + + /// Returns a [`UnitOutput`] which represents some information about the + /// output of a unit. + pub fn unit_output(&self, unit: &Unit, path: &Path) -> UnitOutput { + let script_meta = self.find_build_script_metadata(unit); + UnitOutput { + unit: unit.clone(), + path: path.to_path_buf(), + script_meta, + } + } + + /// Check if any output file name collision happens. + /// See for more. + #[tracing::instrument(skip_all)] + fn check_collisions(&self) -> CargoResult<()> { + let mut output_collisions = HashMap::new(); + let describe_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> String { + format!( + "The {} target `{}` in package `{}` has the same output \ + filename as the {} target `{}` in package `{}`.\n\ + Colliding filename is: {}\n", + unit.target.kind().description(), + unit.target.name(), + unit.pkg.package_id(), + other_unit.target.kind().description(), + other_unit.target.name(), + other_unit.pkg.package_id(), + path.display() + ) + }; + let suggestion = + "Consider changing their names to be unique or compiling them separately.\n\ + This may become a hard error in the future; see \ + ."; + let rustdoc_suggestion = + "This is a known bug where multiple crates with the same name use\n\ + the same path; see ."; + let report_collision = |unit: &Unit, + other_unit: &Unit, + path: &PathBuf, + suggestion: &str| + -> CargoResult<()> { + if unit.target.name() == other_unit.target.name() { + self.bcx.gctx.shell().warn(format!( + "output filename collision.\n\ + {}\ + The targets should have unique names.\n\ + {}", + describe_collision(unit, other_unit, path), + suggestion + )) + } else { + self.bcx.gctx.shell().warn(format!( + "output filename collision.\n\ + {}\ + The output filenames should be unique.\n\ + {}\n\ + If this looks unexpected, it may be a bug in Cargo. Please file a bug report at\n\ + https://github.com/rust-lang/cargo/issues/ with as much information as you\n\ + can provide.\n\ + cargo {} running on `{}` target `{}`\n\ + First unit: {:?}\n\ + Second unit: {:?}", + describe_collision(unit, other_unit, path), + suggestion, + crate::version(), + self.bcx.host_triple(), + self.bcx.target_data.short_name(&unit.kind), + unit, + other_unit)) + } + }; + + fn doc_collision_error(unit: &Unit, other_unit: &Unit) -> CargoResult<()> { + bail!( + "document output filename collision\n\ + The {} `{}` in package `{}` has the same name as the {} `{}` in package `{}`.\n\ + Only one may be documented at once since they output to the same path.\n\ + Consider documenting only one, renaming one, \ + or marking one with `doc = false` in Cargo.toml.", + unit.target.kind().description(), + unit.target.name(), + unit.pkg, + other_unit.target.kind().description(), + other_unit.target.name(), + other_unit.pkg, + ); + } + + let mut keys = self + .bcx + .unit_graph + .keys() + .filter(|unit| !unit.mode.is_run_custom_build()) + .collect::>(); + // Sort for consistent error messages. + keys.sort_unstable(); + // These are kept separate to retain compatibility with older + // versions, which generated an error when there was a duplicate lib + // or bin (but the old code did not check bin<->lib collisions). To + // retain backwards compatibility, this only generates an error for + // duplicate libs or duplicate bins (but not both). Ideally this + // shouldn't be here, but since there isn't a complete workaround, + // yet, this retains the old behavior. + let mut doc_libs = HashMap::new(); + let mut doc_bins = HashMap::new(); + for unit in keys { + if unit.mode.is_doc() && self.is_primary_package(unit) { + // These situations have been an error since before 1.0, so it + // is not a warning like the other situations. + if unit.target.is_lib() { + if let Some(prev) = doc_libs.insert((unit.target.crate_name(), unit.kind), unit) + { + doc_collision_error(unit, prev)?; + } + } else if let Some(prev) = + doc_bins.insert((unit.target.crate_name(), unit.kind), unit) + { + doc_collision_error(unit, prev)?; + } + } + for output in self.outputs(unit)?.iter() { + if let Some(other_unit) = output_collisions.insert(output.path.clone(), unit) { + if unit.mode.is_doc() { + // See https://github.com/rust-lang/rust/issues/56169 + // and https://github.com/rust-lang/rust/issues/61378 + report_collision(unit, other_unit, &output.path, rustdoc_suggestion)?; + } else { + report_collision(unit, other_unit, &output.path, suggestion)?; + } + } + if let Some(hardlink) = output.hardlink.as_ref() { + if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) { + report_collision(unit, other_unit, hardlink, suggestion)?; + } + } + 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!( + "`--artifact-dir` filename collision.\n\ + {}\ + The exported filenames should be unique.\n\ + {}", + describe_collision(unit, other_unit, export_path), + suggestion + ))?; + } + } + } + } + Ok(()) + } + + /// Records the list of units which are required to emit metadata. + /// + /// Units which depend only on the metadata of others requires the others to + /// actually produce metadata, so we'll record that here. + fn record_units_requiring_metadata(&mut self) { + for (key, deps) in self.bcx.unit_graph.iter() { + for dep in deps { + if self.only_requires_rmeta(key, &dep.unit) { + self.rmeta_required.insert(dep.unit.clone()); + } + } + } + } + + /// Returns whether when `parent` depends on `dep` if it only requires the + /// metadata file from `dep`. + pub fn only_requires_rmeta(&self, parent: &Unit, dep: &Unit) -> bool { + // We're only a candidate for requiring an `rmeta` file if we + // ourselves are building an rlib, + !parent.requires_upstream_objects() + && parent.mode == CompileMode::Build + // Our dependency must also be built as an rlib, otherwise the + // object code must be useful in some fashion + && !dep.requires_upstream_objects() + && dep.mode == CompileMode::Build + } + + /// Returns whether when `unit` is built whether it should emit metadata as + /// well because some compilations rely on that. + pub fn rmeta_required(&self, unit: &Unit) -> bool { + self.rmeta_required.contains(unit) + } + + /// Finds metadata for Doc/Docscrape units. + /// + /// rustdoc needs a -Cmetadata flag in order to recognize StableCrateIds that refer to + /// items in the crate being documented. The -Cmetadata flag used by reverse-dependencies + /// will be the metadata of the Cargo unit that generated the current library's rmeta file, + /// which should be a Check unit. + /// + /// If the current crate has reverse-dependencies, such a Check unit should exist, and so + /// we use that crate's metadata. If not, we use the crate's Doc unit so at least examples + /// scraped from the current crate can be used when documenting the current crate. + #[tracing::instrument(skip_all)] + pub fn compute_metadata_for_doc_units(&mut self) { + for unit in self.bcx.unit_graph.keys() { + if !unit.mode.is_doc() && !unit.mode.is_doc_scrape() { + continue; + } + + let matching_units = self + .bcx + .unit_graph + .keys() + .filter(|other| { + unit.pkg == other.pkg + && unit.target == other.target + && !other.mode.is_doc_scrape() + }) + .collect::>(); + let metadata_unit = matching_units + .iter() + .find(|other| other.mode.is_check()) + .or_else(|| matching_units.iter().find(|other| other.mode.is_doc())) + .unwrap_or(&unit); + self.metadata_for_doc_units + .insert(unit.clone(), self.files().metadata(metadata_unit)); + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compilation.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compilation.rs new file mode 100644 index 000000000..c30343ef1 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compilation.rs @@ -0,0 +1,502 @@ +//! Type definitions for the result of a compilation. + +use std::collections::{BTreeSet, HashMap}; +use std::ffi::{OsStr, OsString}; +use std::path::PathBuf; + +use cargo_platform::CfgExpr; +use cargo_util::{paths, ProcessBuilder}; + +use crate::core::compiler::apply_env_config; +use crate::core::compiler::BuildContext; +use crate::core::compiler::{CompileKind, Unit, UnitHash}; +use crate::core::Package; +use crate::util::{context, CargoResult, GlobalContext}; + +/// Represents the kind of process we are creating. +#[derive(Debug)] +enum ToolKind { + /// See [`Compilation::rustc_process`]. + Rustc, + /// See [`Compilation::rustdoc_process`]. + Rustdoc, + /// See [`Compilation::host_process`]. + HostProcess, + /// See [`Compilation::target_process`]. + TargetProcess, +} + +impl ToolKind { + fn is_rustc_tool(&self) -> bool { + matches!(self, ToolKind::Rustc | ToolKind::Rustdoc) + } +} + +/// Structure with enough information to run `rustdoc --test`. +pub struct Doctest { + /// What's being doctested + pub unit: Unit, + /// Arguments needed to pass to rustdoc to run this test. + pub args: Vec, + /// Whether or not -Zunstable-options is needed. + pub unstable_opts: bool, + /// The -Clinker value to use. + pub linker: Option, + /// The script metadata, if this unit's package has a build script. + /// + /// This is used for indexing [`Compilation::extra_env`]. + pub script_meta: Option, + + /// Environment variables to set in the rustdoc process. + pub env: HashMap, +} + +/// Information about the output of a unit. +#[derive(Ord, PartialOrd, Eq, PartialEq)] +pub struct UnitOutput { + /// The unit that generated this output. + pub unit: Unit, + /// Path to the unit's primary output (an executable or cdylib). + pub path: PathBuf, + /// The script metadata, if this unit's package has a build script. + /// + /// This is used for indexing [`Compilation::extra_env`]. + pub script_meta: Option, +} + +/// A structure returning the result of a compilation. +pub struct Compilation<'gctx> { + /// An array of all tests created during this compilation. + pub tests: Vec, + + /// An array of all binaries created. + pub binaries: Vec, + + /// An array of all cdylibs created. + pub cdylibs: Vec, + + /// The crate names of the root units specified on the command-line. + pub root_crate_names: Vec, + + /// All directories for the output of native build commands. + /// + /// This is currently used to drive some entries which are added to the + /// `LD_LIBRARY_PATH` as appropriate. + /// + /// The order should be deterministic. + pub native_dirs: BTreeSet, + + /// Root output directory (for the local package's artifacts) + pub root_output: HashMap, + + /// Output directory for rust dependencies. + /// May be for the host or for a specific target. + pub deps_output: HashMap, + + /// The path to libstd for each target + sysroot_target_libdir: HashMap, + + /// Extra environment variables that were passed to compilations and should + /// be passed to future invocations of programs. + /// + /// The key is the build script metadata for uniquely identifying the + /// `RunCustomBuild` unit that generated these env vars. + pub extra_env: HashMap>, + + /// Libraries to test with rustdoc. + pub to_doc_test: Vec, + + /// The target host triple. + pub host: String, + + gctx: &'gctx GlobalContext, + + /// Rustc process to be used by default + rustc_process: ProcessBuilder, + /// Rustc process to be used for workspace crates instead of `rustc_process` + rustc_workspace_wrapper_process: ProcessBuilder, + /// Optional rustc process to be used for primary crates instead of either `rustc_process` or + /// `rustc_workspace_wrapper_process` + primary_rustc_process: Option, + + target_runners: HashMap)>>, + /// The linker to use for each host or target. + target_linkers: HashMap>, + + /// The total number of warnings emitted by the compilation. + pub warning_count: usize, +} + +impl<'gctx> Compilation<'gctx> { + pub fn new<'a>(bcx: &BuildContext<'a, 'gctx>) -> CargoResult> { + let rustc_process = bcx.rustc().process(); + let primary_rustc_process = bcx.build_config.primary_unit_rustc.clone(); + let rustc_workspace_wrapper_process = bcx.rustc().workspace_process(); + Ok(Compilation { + native_dirs: BTreeSet::new(), + root_output: HashMap::new(), + deps_output: HashMap::new(), + sysroot_target_libdir: get_sysroot_target_libdir(bcx)?, + tests: Vec::new(), + binaries: Vec::new(), + cdylibs: Vec::new(), + root_crate_names: Vec::new(), + extra_env: HashMap::new(), + to_doc_test: Vec::new(), + gctx: bcx.gctx, + host: bcx.host_triple().to_string(), + rustc_process, + rustc_workspace_wrapper_process, + primary_rustc_process, + target_runners: bcx + .build_config + .requested_kinds + .iter() + .chain(Some(&CompileKind::Host)) + .map(|kind| Ok((*kind, target_runner(bcx, *kind)?))) + .collect::>>()?, + target_linkers: bcx + .build_config + .requested_kinds + .iter() + .chain(Some(&CompileKind::Host)) + .map(|kind| Ok((*kind, target_linker(bcx, *kind)?))) + .collect::>>()?, + warning_count: 0, + }) + } + + /// Returns a [`ProcessBuilder`] for running `rustc`. + /// + /// `is_primary` is true if this is a "primary package", which means it + /// was selected by the user on the command-line (such as with a `-p` + /// flag), see [`crate::core::compiler::BuildRunner::primary_packages`]. + /// + /// `is_workspace` is true if this is a workspace member. + pub fn rustc_process( + &self, + unit: &Unit, + is_primary: bool, + is_workspace: bool, + ) -> CargoResult { + let mut rustc = if is_primary && self.primary_rustc_process.is_some() { + self.primary_rustc_process.clone().unwrap() + } else if is_workspace { + self.rustc_workspace_wrapper_process.clone() + } else { + self.rustc_process.clone() + }; + if self.gctx.extra_verbose() { + rustc.display_env_vars(); + } + let cmd = fill_rustc_tool_env(rustc, unit); + self.fill_env(cmd, &unit.pkg, None, unit.kind, ToolKind::Rustc) + } + + /// Returns a [`ProcessBuilder`] for running `rustdoc`. + pub fn rustdoc_process( + &self, + unit: &Unit, + script_meta: Option, + ) -> CargoResult { + let mut rustdoc = ProcessBuilder::new(&*self.gctx.rustdoc()?); + if self.gctx.extra_verbose() { + rustdoc.display_env_vars(); + } + let cmd = fill_rustc_tool_env(rustdoc, unit); + let mut cmd = self.fill_env(cmd, &unit.pkg, script_meta, unit.kind, ToolKind::Rustdoc)?; + cmd.retry_with_argfile(true); + unit.target.edition().cmd_edition_arg(&mut cmd); + + for crate_type in unit.target.rustc_crate_types() { + cmd.arg("--crate-type").arg(crate_type.as_str()); + } + + Ok(cmd) + } + + /// Returns a [`ProcessBuilder`] appropriate for running a process for the + /// host platform. + /// + /// This is currently only used for running build scripts. If you use this + /// for anything else, please be extra careful on how environment + /// variables are set! + pub fn host_process>( + &self, + cmd: T, + pkg: &Package, + ) -> CargoResult { + self.fill_env( + ProcessBuilder::new(cmd), + pkg, + None, + CompileKind::Host, + ToolKind::HostProcess, + ) + } + + pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec)> { + 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 { + 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`. + /// + /// `script_meta` is the metadata for the `RunCustomBuild` unit that this + /// unit used for its build script. Use `None` if the package did not have + /// a build script. + pub fn target_process>( + &self, + cmd: T, + kind: CompileKind, + pkg: &Package, + script_meta: Option, + ) -> CargoResult { + let builder = if let Some((runner, args)) = self.target_runner(kind) { + let mut builder = ProcessBuilder::new(runner); + builder.args(args); + builder.arg(cmd); + builder + } else { + ProcessBuilder::new(cmd) + }; + let tool_kind = ToolKind::TargetProcess; + let mut builder = self.fill_env(builder, pkg, script_meta, kind, tool_kind)?; + + if let Some(client) = self.gctx.jobserver_from_env() { + builder.inherit_jobserver(client); + } + + Ok(builder) + } + + /// Prepares a new process with an appropriate environment to run against + /// the artifacts produced by the build process. + /// + /// The package argument is also used to configure environment variables as + /// well as the working directory of the child process. + fn fill_env( + &self, + mut cmd: ProcessBuilder, + pkg: &Package, + script_meta: Option, + kind: CompileKind, + tool_kind: ToolKind, + ) -> CargoResult { + let mut search_path = Vec::new(); + if tool_kind.is_rustc_tool() { + if matches!(tool_kind, ToolKind::Rustdoc) { + // HACK: `rustdoc --test` not only compiles but executes doctests. + // Ideally only execution phase should have search paths appended, + // so the executions can find native libs just like other tests. + // However, there is no way to separate these two phase, so this + // hack is added for both phases. + // TODO: handle doctest-xcompile + search_path.extend(super::filter_dynamic_search_path( + self.native_dirs.iter(), + &self.root_output[&CompileKind::Host], + )); + } + search_path.push(self.deps_output[&CompileKind::Host].clone()); + } else { + search_path.extend(super::filter_dynamic_search_path( + self.native_dirs.iter(), + &self.root_output[&kind], + )); + search_path.push(self.deps_output[&kind].clone()); + search_path.push(self.root_output[&kind].clone()); + // For build-std, we don't want to accidentally pull in any shared + // libs from the sysroot that ships with rustc. This may not be + // required (at least I cannot craft a situation where it + // matters), but is here to be safe. + if self.gctx.cli_unstable().build_std.is_none() || + // Proc macros dynamically link to std, so set it anyway. + pkg.proc_macro() + { + search_path.push(self.sysroot_target_libdir[&kind].clone()); + } + } + + let dylib_path = paths::dylib_path(); + let dylib_path_is_empty = dylib_path.is_empty(); + if dylib_path.starts_with(&search_path) { + search_path = dylib_path; + } else { + search_path.extend(dylib_path.into_iter()); + } + if cfg!(target_os = "macos") && dylib_path_is_empty { + // These are the defaults when DYLD_FALLBACK_LIBRARY_PATH isn't + // set or set to an empty string. Since Cargo is explicitly setting + // the value, make sure the defaults still work. + if let Some(home) = self.gctx.get_env_os("HOME") { + search_path.push(PathBuf::from(home).join("lib")); + } + search_path.push(PathBuf::from("/usr/local/lib")); + search_path.push(PathBuf::from("/usr/lib")); + } + let search_path = paths::join_paths(&search_path, paths::dylib_path_envvar())?; + + cmd.env(paths::dylib_path_envvar(), &search_path); + if let Some(meta) = script_meta { + if let Some(env) = self.extra_env.get(&meta) { + for (k, v) in env { + cmd.env(k, v); + } + } + } + + let cargo_exe = self.gctx.cargo_exe()?; + cmd.env(crate::CARGO_ENV, cargo_exe); + + // When adding new environment variables depending on + // crate properties which might require rebuild upon change + // consider adding the corresponding properties to the hash + // in BuildContext::target_metadata() + cmd.env("CARGO_MANIFEST_DIR", pkg.root()) + .env("CARGO_MANIFEST_PATH", pkg.manifest_path()) + .env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string()) + .env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string()) + .env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string()) + .env("CARGO_PKG_VERSION_PRE", pkg.version().pre.as_str()) + .env("CARGO_PKG_VERSION", &pkg.version().to_string()) + .env("CARGO_PKG_NAME", &*pkg.name()); + + for (key, value) in pkg.manifest().metadata().env_vars() { + cmd.env(key, value.as_ref()); + } + + cmd.cwd(pkg.root()); + + apply_env_config(self.gctx, &mut cmd)?; + + Ok(cmd) + } +} + +/// Prepares a `rustc_tool` process with additional environment variables +/// that are only relevant in a context that has a unit +fn fill_rustc_tool_env(mut cmd: ProcessBuilder, unit: &Unit) -> ProcessBuilder { + if unit.target.is_executable() { + let name = unit + .target + .binary_filename() + .unwrap_or(unit.target.name().to_string()); + + cmd.env("CARGO_BIN_NAME", name); + } + cmd.env("CARGO_CRATE_NAME", unit.target.crate_name()); + cmd +} + +fn get_sysroot_target_libdir( + bcx: &BuildContext<'_, '_>, +) -> CargoResult> { + bcx.all_kinds + .iter() + .map(|&kind| { + let Some(info) = bcx.target_data.get_info(kind) else { + let target = match kind { + CompileKind::Host => "host".to_owned(), + CompileKind::Target(s) => s.short_name().to_owned(), + }; + + let dependency = bcx + .unit_graph + .iter() + .find_map(|(u, _)| (u.kind == kind).then_some(u.pkg.summary().package_id())) + .unwrap(); + + anyhow::bail!( + "could not find specification for target `{target}`.\n \ + Dependency `{dependency}` requires to build for target `{target}`." + ) + }; + + Ok((kind, info.sysroot_target_libdir.clone())) + }) + .collect() +} + +fn target_runner( + bcx: &BuildContext<'_, '_>, + kind: CompileKind, +) -> CargoResult)>> { + let target = bcx.target_data.short_name(&kind); + + // try target.{}.runner + let key = format!("target.{}.runner", target); + + if let Some(v) = bcx.gctx.get::>(&key)? { + let path = v.path.resolve_program(bcx.gctx); + return Ok(Some((path, v.args))); + } + + // try target.'cfg(...)'.runner + let target_cfg = bcx.target_data.info(kind).cfg(); + let mut cfgs = bcx + .gctx + .target_cfgs()? + .iter() + .filter_map(|(key, cfg)| cfg.runner.as_ref().map(|runner| (key, runner))) + .filter(|(key, _runner)| CfgExpr::matches_key(key, target_cfg)); + let matching_runner = cfgs.next(); + if let Some((key, runner)) = cfgs.next() { + anyhow::bail!( + "several matching instances of `target.'cfg(..)'.runner` in configurations\n\ + first match `{}` located in {}\n\ + second match `{}` located in {}", + matching_runner.unwrap().0, + matching_runner.unwrap().1.definition, + key, + runner.definition + ); + } + Ok(matching_runner.map(|(_k, runner)| { + ( + runner.val.path.clone().resolve_program(bcx.gctx), + runner.val.args.clone(), + ) + })) +} + +/// Gets the user-specified linker for a particular host or target from the configuration. +fn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult> { + // 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.gctx)) + { + return Ok(Some(path)); + } + + // Try target.'cfg(...)'.linker. + let target_cfg = bcx.target_data.info(kind).cfg(); + let mut cfgs = bcx + .gctx + .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.gctx))) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compile_kind.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compile_kind.rs new file mode 100644 index 000000000..deb518afb --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/compile_kind.rs @@ -0,0 +1,200 @@ +//! Type definitions for cross-compilation. + +use crate::core::Target; +use crate::util::errors::CargoResult; +use crate::util::interning::InternedString; +use crate::util::{try_canonicalize, GlobalContext, StableHasher}; +use anyhow::Context as _; +use serde::Serialize; +use std::collections::BTreeSet; +use std::fs; +use std::hash::{Hash, Hasher}; +use std::path::Path; + +/// Indicator for how a unit is being compiled. +/// +/// This is used primarily for organizing cross compilations vs host +/// compilations, where cross compilations happen at the request of `--target` +/// and host compilations happen for things like build scripts and procedural +/// macros. +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord)] +pub enum CompileKind { + /// Attached to a unit that is compiled for the "host" system or otherwise + /// is compiled without a `--target` flag. This is used for procedural + /// macros and build scripts, or if the `--target` flag isn't passed. + Host, + + /// Attached to a unit to be compiled for a particular target. This is used + /// for units when the `--target` flag is passed. + Target(CompileTarget), +} + +impl CompileKind { + pub fn is_host(&self) -> bool { + matches!(self, CompileKind::Host) + } + + pub fn for_target(self, target: &Target) -> CompileKind { + // Once we start compiling for the `Host` kind we continue doing so, but + // if we are a `Target` kind and then we start compiling for a target + // that needs to be on the host we lift ourselves up to `Host`. + match self { + CompileKind::Host => CompileKind::Host, + CompileKind::Target(_) if target.for_host() => CompileKind::Host, + CompileKind::Target(n) => CompileKind::Target(n), + } + } + + /// Creates a new list of `CompileKind` based on the requested list of + /// targets. + /// + /// If no targets are given then this returns a single-element vector with + /// `CompileKind::Host`. + pub fn from_requested_targets( + gctx: &GlobalContext, + targets: &[String], + ) -> CargoResult> { + let dedup = |targets: &[String]| { + Ok(targets + .iter() + .map(|value| Ok(CompileKind::Target(CompileTarget::new(value)?))) + // First collect into a set to deduplicate any `--target` passed + // more than once... + .collect::>>()? + // ... then generate a flat list for everything else to use. + .into_iter() + .collect()) + }; + + if !targets.is_empty() { + return dedup(targets); + } + + let kinds = match &gctx.build_config()?.target { + None => Ok(vec![CompileKind::Host]), + Some(build_target_config) => dedup(&build_target_config.values(gctx)?), + }; + + kinds + } + + /// Hash used for fingerprinting. + /// + /// Metadata hashing uses the normal Hash trait, which does not + /// differentiate on `.json` file contents. The fingerprint hash does + /// check the contents. + pub fn fingerprint_hash(&self) -> u64 { + match self { + CompileKind::Host => 0, + CompileKind::Target(target) => target.fingerprint_hash(), + } + } +} + +impl serde::ser::Serialize for CompileKind { + fn serialize(&self, s: S) -> Result + where + S: serde::ser::Serializer, + { + match self { + CompileKind::Host => None::<&str>.serialize(s), + CompileKind::Target(t) => Some(t.name).serialize(s), + } + } +} + +/// Abstraction for the representation of a compilation target that Cargo has. +/// +/// Compilation targets are one of two things right now: +/// +/// 1. A raw target string, like `x86_64-unknown-linux-gnu`. +/// 2. The path to a JSON file, such as `/path/to/my-target.json`. +/// +/// Raw target strings are typically dictated by `rustc` itself and represent +/// built-in targets. Custom JSON files are somewhat unstable, but supported +/// here in Cargo. Note that for JSON target files this `CompileTarget` stores a +/// full canonicalized path to the target. +/// +/// The main reason for this existence is to handle JSON target files where when +/// we call rustc we pass full paths but when we use it for Cargo's purposes +/// like naming directories or looking up configuration keys we only check the +/// file stem of JSON target files. For built-in rustc targets this is just an +/// uninterpreted string basically. +#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, PartialOrd, Ord, Serialize)] +pub struct CompileTarget { + name: InternedString, +} + +impl CompileTarget { + pub fn new(name: &str) -> CargoResult { + let name = name.trim(); + if name.is_empty() { + anyhow::bail!("target was empty"); + } + if !name.ends_with(".json") { + return Ok(CompileTarget { name: name.into() }); + } + + // If `name` ends in `.json` then it's likely a custom target + // specification. Canonicalize the path to ensure that different builds + // with different paths always produce the same result. + let path = try_canonicalize(Path::new(name)) + .with_context(|| format!("target path {:?} is not a valid file", name))?; + + let name = path + .into_os_string() + .into_string() + .map_err(|_| anyhow::format_err!("target path is not valid unicode"))?; + Ok(CompileTarget { name: name.into() }) + } + + /// Returns the full unqualified name of this target, suitable for passing + /// to `rustc` directly. + /// + /// Typically this is pretty much the same as `short_name`, but for the case + /// of JSON target files this will be a full canonicalized path name for the + /// current filesystem. + pub fn rustc_target(&self) -> InternedString { + self.name + } + + /// Returns a "short" version of the target name suitable for usage within + /// Cargo for configuration and such. + /// + /// This is typically the same as `rustc_target`, or the full name, but for + /// JSON target files this returns just the file stem (e.g. `foo` out of + /// `foo.json`) instead of the full path. + pub fn short_name(&self) -> &str { + // Flexible target specifications often point at json files, so if it + // looks like we've got one of those just use the file stem (the file + // name without ".json") as a short name for this target. Note that the + // `unwrap()` here should never trigger since we have a nonempty name + // and it starts as utf-8 so it's always utf-8 + if self.name.ends_with(".json") { + Path::new(&self.name).file_stem().unwrap().to_str().unwrap() + } else { + &self.name + } + } + + /// See [`CompileKind::fingerprint_hash`]. + pub fn fingerprint_hash(&self) -> u64 { + let mut hasher = StableHasher::new(); + match self + .name + .ends_with(".json") + .then(|| fs::read_to_string(self.name)) + { + Some(Ok(contents)) => { + // This may have some performance concerns, since it is called + // fairly often. If that ever seems worth fixing, consider + // embedding this in `CompileTarget`. + contents.hash(&mut hasher); + } + _ => { + self.name.hash(&mut hasher); + } + } + Hasher::finish(&hasher) + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/crate_type.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/crate_type.rs new file mode 100644 index 000000000..a36ef6c0f --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/crate_type.rs @@ -0,0 +1,115 @@ +use std::fmt; + +/// Types of the output artifact that the compiler emits. +/// Usually distributable or linkable either statically or dynamically. +/// +/// See . +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum CrateType { + Bin, + Lib, + Rlib, + Dylib, + Cdylib, + Staticlib, + ProcMacro, + Other(String), +} + +impl CrateType { + pub fn as_str(&self) -> &str { + match self { + CrateType::Bin => "bin", + CrateType::Lib => "lib", + CrateType::Rlib => "rlib", + CrateType::Dylib => "dylib", + CrateType::Cdylib => "cdylib", + CrateType::Staticlib => "staticlib", + CrateType::ProcMacro => "proc-macro", + CrateType::Other(s) => s, + } + } + + pub fn can_lto(&self) -> bool { + match self { + CrateType::Bin | CrateType::Staticlib | CrateType::Cdylib => true, + CrateType::Lib + | CrateType::Rlib + | CrateType::Dylib + | CrateType::ProcMacro + | CrateType::Other(..) => false, + } + } + + pub fn is_linkable(&self) -> bool { + match self { + CrateType::Lib | CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true, + CrateType::Bin | CrateType::Cdylib | CrateType::Staticlib | CrateType::Other(..) => { + false + } + } + } + + pub fn is_dynamic(&self) -> bool { + match self { + CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => true, + CrateType::Lib + | CrateType::Rlib + | CrateType::Bin + | CrateType::Staticlib + | CrateType::Other(..) => false, + } + } + + /// Returns whether production of this crate type requires the object files + /// from dependencies to be available. + /// + /// See also [`TargetKind::requires_upstream_objects`]. + /// + /// [`TargetKind::requires_upstream_objects`]: crate::core::manifest::TargetKind::requires_upstream_objects + pub fn requires_upstream_objects(&self) -> bool { + // "lib" == "rlib" and is a compilation that doesn't actually + // require upstream object files to exist, only upstream metadata + // files. As a result, it doesn't require upstream artifacts + + !matches!(self, CrateType::Lib | CrateType::Rlib) + // Everything else, however, is some form of "linkable output" or + // something that requires upstream object files. + } +} + +impl fmt::Display for CrateType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_str().fmt(f) + } +} + +impl<'a> From<&'a String> for CrateType { + fn from(s: &'a String) -> Self { + match s.as_str() { + "bin" => CrateType::Bin, + "lib" => CrateType::Lib, + "rlib" => CrateType::Rlib, + "dylib" => CrateType::Dylib, + "cdylib" => CrateType::Cdylib, + "staticlib" => CrateType::Staticlib, + "procmacro" => CrateType::ProcMacro, + _ => CrateType::Other(s.clone()), + } + } +} + +impl fmt::Debug for CrateType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.to_string().fmt(f) + } +} + +impl serde::Serialize for CrateType { + fn serialize(&self, s: S) -> Result + where + S: serde::ser::Serializer, + { + self.to_string().serialize(s) + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/custom_build.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/custom_build.rs new file mode 100644 index 000000000..9f7287baa --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/custom_build.rs @@ -0,0 +1,1336 @@ +//! How to execute a build script and parse its output. +//! +//! ## Preparing a build script run +//! +//! A [build script] is an optional Rust script Cargo will run before building +//! your package. As of this writing, two kinds of special [`Unit`]s will be +//! constructed when there is a build script in a package. +//! +//! * Build script compilation --- This unit is generally the same as units +//! that would compile other Cargo targets. It will recursively creates units +//! of its dependencies. One biggest difference is that the [`Unit`] of +//! compiling a build script is flagged as [`TargetKind::CustomBuild`]. +//! * Build script execution --- During the construction of the [`UnitGraph`], +//! Cargo inserts a [`Unit`] with [`CompileMode::RunCustomBuild`]. This unit +//! depends on the unit of compiling the associated build script, to ensure +//! the executable is available before running. The [`Work`] of running the +//! build script is prepared in the function [`prepare`]. +//! +//! ## Running a build script +//! +//! When running a build script, Cargo is aware of the progress and the result +//! of a build script. Standard output is the chosen interprocess communication +//! between Cargo and build script processes. A set of strings is defined for +//! that purpose. These strings, a.k.a. instructions, are interpreted by +//! [`BuildOutput::parse`] and stored in [`BuildRunner::build_script_outputs`]. +//! The entire execution work is constructed by [`build_work`]. +//! +//! [build script]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html +//! [`TargetKind::CustomBuild`]: crate::core::manifest::TargetKind::CustomBuild +//! [`UnitGraph`]: super::unit_graph::UnitGraph +//! [`CompileMode::RunCustomBuild`]: super::CompileMode +//! [instructions]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script + +use super::{fingerprint, BuildRunner, Job, Unit, Work}; +use crate::core::compiler::artifact; +use crate::core::compiler::build_runner::UnitHash; +use crate::core::compiler::fingerprint::DirtyReason; +use crate::core::compiler::job_queue::JobState; +use crate::core::{profiles::ProfileRoot, PackageId, Target}; +use crate::util::errors::CargoResult; +use crate::util::internal; +use crate::util::machine_message::{self, Message}; +use anyhow::{bail, Context as _}; +use cargo_platform::Cfg; +use cargo_util::paths; +use cargo_util_schemas::manifest::RustVersion; +use std::collections::hash_map::{Entry, HashMap}; +use std::collections::{BTreeSet, HashSet}; +use std::path::{Path, PathBuf}; +use std::str::{self, FromStr}; +use std::sync::{Arc, Mutex}; + +/// A build script instruction that tells Cargo to display an error after the +/// build script has finished running. Read [the doc] for more. +/// +/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-error +const CARGO_ERROR_SYNTAX: &str = "cargo::error="; +/// Deprecated: A build script instruction that tells Cargo to display a warning after the +/// build script has finished running. Read [the doc] for more. +/// +/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning +const OLD_CARGO_WARNING_SYNTAX: &str = "cargo:warning="; +/// A build script instruction that tells Cargo to display a warning after the +/// build script has finished running. Read [the doc] for more. +/// +/// [the doc]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargo-warning +const NEW_CARGO_WARNING_SYNTAX: &str = "cargo::warning="; + +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub enum Severity { + Error, + Warning, +} + +pub type LogMessage = (Severity, String); + +/// Contains the parsed output of a custom build script. +#[derive(Clone, Debug, Hash, Default, PartialEq, Eq, PartialOrd, Ord)] +pub struct BuildOutput { + /// Paths to pass to rustc with the `-L` flag. + pub library_paths: Vec, + /// Names and link kinds of libraries, suitable for the `-l` flag. + pub library_links: Vec, + /// Linker arguments suitable to be passed to `-C link-arg=` + pub linker_args: Vec<(LinkArgTarget, String)>, + /// Various `--cfg` flags to pass to the compiler. + pub cfgs: Vec, + /// Various `--check-cfg` flags to pass to the compiler. + pub check_cfgs: Vec, + /// Additional environment variables to run the compiler with. + pub env: Vec<(String, String)>, + /// Metadata to pass to the immediate dependencies. + pub metadata: Vec<(String, String)>, + /// Paths to trigger a rerun of this build script. + /// May be absolute or relative paths (relative to package root). + pub rerun_if_changed: Vec, + /// Environment variables which, when changed, will cause a rebuild. + pub rerun_if_env_changed: Vec, + /// Errors and warnings generated by this build. + /// + /// These are only displayed if this is a "local" package, `-vv` is used, or + /// there is a build error for any target in this package. Note that any log + /// message of severity `Error` will by itself cause a build error, and will + /// cause all log messages to be displayed. + pub log_messages: Vec, +} + +/// Map of packages to build script output. +/// +/// This initially starts out as empty. Overridden build scripts get +/// inserted during `build_map`. The rest of the entries are added +/// immediately after each build script runs. +/// +/// The [`UnitHash`] is the unique metadata hash for the `RunCustomBuild` Unit of +/// the package. It needs a unique key, since the build script can be run +/// multiple times with different profiles or features. We can't embed a +/// `Unit` because this structure needs to be shareable between threads. +#[derive(Default)] +pub struct BuildScriptOutputs { + outputs: HashMap, +} + +/// Linking information for a `Unit`. +/// +/// See [`build_map`] for more details. +#[derive(Default)] +pub struct BuildScripts { + /// List of build script outputs this Unit needs to include for linking. Each + /// element is an index into `BuildScriptOutputs`. + /// + /// Cargo will use this `to_link` vector to add `-L` flags to compiles as we + /// propagate them upwards towards the final build. Note, however, that we + /// need to preserve the ordering of `to_link` to be topologically sorted. + /// This will ensure that build scripts which print their paths properly will + /// correctly pick up the files they generated (if there are duplicates + /// elsewhere). + /// + /// To preserve this ordering, the (id, metadata) is stored in two places, once + /// in the `Vec` and once in `seen_to_link` for a fast lookup. We maintain + /// this as we're building interactively below to ensure that the memory + /// usage here doesn't blow up too much. + /// + /// For more information, see #2354. + pub to_link: Vec<(PackageId, UnitHash)>, + /// This is only used while constructing `to_link` to avoid duplicates. + seen_to_link: HashSet<(PackageId, UnitHash)>, + /// Host-only dependencies that have build scripts. Each element is an + /// index into `BuildScriptOutputs`. + /// + /// This is the set of transitive dependencies that are host-only + /// (proc-macro, plugin, build-dependency) that contain a build script. + /// Any `BuildOutput::library_paths` path relative to `target` will be + /// added to `LD_LIBRARY_PATH` so that the compiler can find any dynamic + /// libraries a build script may have generated. + pub plugins: BTreeSet<(PackageId, UnitHash)>, +} + +/// Dependency information as declared by a build script that might trigger +/// a recompile of itself. +#[derive(Debug)] +pub struct BuildDeps { + /// Absolute path to the file in the target directory that stores the + /// output of the build script. + pub build_script_output: PathBuf, + /// Files that trigger a rebuild if they change. + pub rerun_if_changed: Vec, + /// Environment variables that trigger a rebuild if they change. + pub rerun_if_env_changed: Vec, +} + +/// Represents one of the instructions from `cargo::rustc-link-arg-*` build +/// script instruction family. +/// +/// In other words, indicates targets that custom linker arguments applies to. +/// +/// See the [build script documentation][1] for more. +/// +/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-link-argflag +#[derive(Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum LinkArgTarget { + /// Represents `cargo::rustc-link-arg=FLAG`. + All, + /// Represents `cargo::rustc-cdylib-link-arg=FLAG`. + Cdylib, + /// Represents `cargo::rustc-link-arg-bins=FLAG`. + Bin, + /// Represents `cargo::rustc-link-arg-bin=BIN=FLAG`. + SingleBin(String), + /// Represents `cargo::rustc-link-arg-tests=FLAG`. + Test, + /// Represents `cargo::rustc-link-arg-benches=FLAG`. + Bench, + /// Represents `cargo::rustc-link-arg-examples=FLAG`. + Example, +} + +impl LinkArgTarget { + /// Checks if this link type applies to a given [`Target`]. + pub fn applies_to(&self, target: &Target) -> bool { + match self { + LinkArgTarget::All => true, + LinkArgTarget::Cdylib => target.is_cdylib(), + LinkArgTarget::Bin => target.is_bin(), + LinkArgTarget::SingleBin(name) => target.is_bin() && target.name() == name, + LinkArgTarget::Test => target.is_test(), + LinkArgTarget::Bench => target.is_bench(), + LinkArgTarget::Example => target.is_exe_example(), + } + } +} + +/// Prepares a `Work` that executes the target as a custom build script. +#[tracing::instrument(skip_all)] +pub fn prepare(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult { + let metadata = build_runner.get_run_build_script_metadata(unit); + if build_runner + .build_script_outputs + .lock() + .unwrap() + .contains_key(metadata) + { + // The output is already set, thus the build script is overridden. + fingerprint::prepare_target(build_runner, unit, false) + } else { + build_work(build_runner, unit) + } +} + +/// Emits the output of a build script as a [`machine_message::BuildScript`] +/// JSON string to standard output. +fn emit_build_output( + state: &JobState<'_, '_>, + output: &BuildOutput, + out_dir: &Path, + package_id: PackageId, +) -> CargoResult<()> { + let library_paths = output + .library_paths + .iter() + .map(|l| l.display().to_string()) + .collect::>(); + + let msg = machine_message::BuildScript { + package_id: package_id.to_spec(), + linked_libs: &output.library_links, + linked_paths: &library_paths, + cfgs: &output.cfgs, + env: &output.env, + out_dir, + } + .to_json_string(); + state.stdout(msg)?; + Ok(()) +} + +/// Constructs the unit of work of running a build script. +/// +/// The construction includes: +/// +/// * 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. +fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult { + assert!(unit.mode.is_run_custom_build()); + let bcx = &build_runner.bcx; + let dependencies = build_runner.unit_deps(unit); + let build_script_unit = dependencies + .iter() + .find(|d| !d.unit.mode.is_run_custom_build() && d.unit.target.is_custom_build()) + .map(|d| &d.unit) + .expect("running a script not depending on an actual script"); + let script_dir = build_runner.files().build_script_dir(build_script_unit); + let script_out_dir = build_runner.files().build_script_out_dir(unit); + let script_run_dir = build_runner.files().build_script_run_dir(unit); + let build_plan = bcx.build_config.build_plan; + let invocation_name = unit.buildkey(); + + if let Some(deps) = unit.pkg.manifest().metabuild() { + prepare_metabuild(build_runner, build_script_unit, deps)?; + } + + // Building the command to execute + let to_exec = script_dir.join(unit.target.name()); + + // Start preparing the process to execute, starting out with some + // environment variables. Note that the profile-related environment + // variables are not set with this the build script's profile but rather the + // package's library profile. + // NOTE: if you add any profile flags, be sure to update + // `Profiles::get_profile_run_custom_build` so that those flags get + // carried over. + let to_exec = to_exec.into_os_string(); + let mut cmd = build_runner.compilation.host_process(to_exec, &unit.pkg)?; + let debug = unit.profile.debuginfo.is_turned_on(); + cmd.env("OUT_DIR", &script_out_dir) + .env("CARGO_MANIFEST_DIR", unit.pkg.root()) + .env("CARGO_MANIFEST_PATH", unit.pkg.manifest_path()) + .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) + .env( + "PROFILE", + match unit.profile.root { + ProfileRoot::Release => "release", + ProfileRoot::Debug => "debug", + }, + ) + .env("HOST", &bcx.host_triple()) + .env("RUSTC", &bcx.rustc().path) + .env("RUSTDOC", &*bcx.gctx.rustdoc()?) + .inherit_jobserver(&build_runner.jobserver); + + // Find all artifact dependencies and make their file and containing directory discoverable using environment variables. + for (var, value) in artifact::get_env(build_runner, dependencies)? { + cmd.env(&var, value); + } + + if let Some(linker) = &build_runner.compilation.target_linker(unit.kind) { + cmd.env("RUSTC_LINKER", linker); + } + + if let Some(links) = unit.pkg.manifest().links() { + cmd.env("CARGO_MANIFEST_LINKS", links); + } + + if let Some(trim_paths) = unit.profile.trim_paths.as_ref() { + cmd.env("CARGO_TRIM_PATHS", trim_paths.to_string()); + } + + // Be sure to pass along all enabled features for this package, this is the + // last piece of statically known information that we have. + for feat in &unit.features { + cmd.env(&format!("CARGO_FEATURE_{}", super::envify(feat)), "1"); + } + + let mut cfg_map = HashMap::new(); + cfg_map.insert( + "feature", + unit.features.iter().map(|s| s.as_str()).collect::>(), + ); + for cfg in bcx.target_data.cfg(unit.kind) { + match *cfg { + Cfg::Name(ref n) => { + cfg_map.insert(n.as_str(), Vec::new()); + } + Cfg::KeyPair(ref k, ref v) => { + let values = cfg_map.entry(k.as_str()).or_default(); + values.push(v.as_str()); + } + } + } + for (k, v) in cfg_map { + if k == "debug_assertions" { + // This cfg is always true and misleading, so avoid setting it. + // That is because Cargo queries rustc without any profile settings. + continue; + } + // FIXME: We should handle raw-idents somehow instead of predenting they + // don't exist here + let k = format!("CARGO_CFG_{}", super::envify(k)); + cmd.env(&k, v.join(",")); + } + + // Also inform the build script of the rustc compiler context. + if let Some(wrapper) = bcx.rustc().wrapper.as_ref() { + cmd.env("RUSTC_WRAPPER", wrapper); + } else { + cmd.env_remove("RUSTC_WRAPPER"); + } + cmd.env_remove("RUSTC_WORKSPACE_WRAPPER"); + if build_runner.bcx.ws.is_member(&unit.pkg) { + if let Some(wrapper) = bcx.rustc().workspace_wrapper.as_ref() { + cmd.env("RUSTC_WORKSPACE_WRAPPER", wrapper); + } + } + cmd.env("CARGO_ENCODED_RUSTFLAGS", unit.rustflags.join("\x1f")); + cmd.env_remove("RUSTFLAGS"); + + if build_runner.bcx.ws.gctx().extra_verbose() { + cmd.display_env_vars(); + } + + // Gather the set of native dependencies that this package has along with + // some other variables to close over. + // + // This information will be used at build-time later on to figure out which + // sorts of variables need to be discovered at that time. + let lib_deps = dependencies + .iter() + .filter_map(|dep| { + if dep.unit.mode.is_run_custom_build() { + let dep_metadata = build_runner.get_run_build_script_metadata(&dep.unit); + Some(( + dep.unit.pkg.manifest().links().unwrap().to_string(), + dep.unit.pkg.package_id(), + dep_metadata, + )) + } else { + None + } + }) + .collect::>(); + let library_name = unit.pkg.library().map(|t| t.crate_name()); + let pkg_descr = unit.pkg.to_string(); + let build_script_outputs = Arc::clone(&build_runner.build_script_outputs); + let id = unit.pkg.package_id(); + let output_file = script_run_dir.join("output"); + let err_file = script_run_dir.join("stderr"); + let root_output_file = script_run_dir.join("root-output"); + let host_target_root = build_runner.files().host_dest().to_path_buf(); + let all = ( + id, + library_name.clone(), + pkg_descr.clone(), + Arc::clone(&build_script_outputs), + output_file.clone(), + script_out_dir.clone(), + ); + let build_scripts = build_runner.build_scripts.get(unit).cloned(); + let json_messages = bcx.build_config.emit_json(); + let extra_verbose = bcx.gctx.extra_verbose(); + let (prev_output, prev_script_out_dir) = prev_build_output(build_runner, unit); + let metadata_hash = build_runner.get_run_build_script_metadata(unit); + + paths::create_dir_all(&script_dir)?; + paths::create_dir_all(&script_out_dir)?; + + let nightly_features_allowed = build_runner.bcx.gctx.nightly_features_allowed; + let targets: Vec = unit.pkg.targets().to_vec(); + let msrv = unit.pkg.rust_version().cloned(); + // Need a separate copy for the fresh closure. + let targets_fresh = targets.clone(); + let msrv_fresh = msrv.clone(); + + let env_profile_name = unit.profile.name.to_uppercase(); + let built_with_debuginfo = build_runner + .bcx + .unit_graph + .get(unit) + .and_then(|deps| deps.iter().find(|dep| dep.unit.target == unit.target)) + .map(|dep| dep.unit.profile.debuginfo.is_turned_on()) + .unwrap_or(false); + + // Prepare the unit of "dirty work" which will actually run the custom build + // command. + // + // Note that this has to do some extra work just before running the command + // to determine extra environment variables and such. + let dirty = Work::new(move |state| { + // Make sure that OUT_DIR exists. + // + // If we have an old build directory, then just move it into place, + // otherwise create it! + paths::create_dir_all(&script_out_dir) + .context("failed to create script output directory for build command")?; + + // For all our native lib dependencies, pick up their metadata to pass + // along to this custom build command. We're also careful to augment our + // dynamic library search path in case the build script depended on any + // native dynamic libraries. + if !build_plan { + let build_script_outputs = build_script_outputs.lock().unwrap(); + for (name, dep_id, dep_metadata) in lib_deps { + let script_output = build_script_outputs.get(dep_metadata).ok_or_else(|| { + internal(format!( + "failed to locate build state for env vars: {}/{}", + dep_id, dep_metadata + )) + })?; + let data = &script_output.metadata; + for (key, value) in data.iter() { + cmd.env( + &format!("DEP_{}_{}", super::envify(&name), super::envify(key)), + value, + ); + } + } + if let Some(build_scripts) = build_scripts { + super::add_plugin_deps( + &mut cmd, + &build_script_outputs, + &build_scripts, + &host_target_root, + )?; + } + } + + if build_plan { + state.build_plan(invocation_name, cmd.clone(), Arc::new(Vec::new())); + return Ok(()); + } + + // And now finally, run the build command itself! + state.running(&cmd); + let timestamp = paths::set_invocation_time(&script_run_dir)?; + let prefix = format!("[{} {}] ", id.name(), id.version()); + let mut log_messages_in_case_of_panic = Vec::new(); + let output = cmd + .exec_with_streaming( + &mut |stdout| { + if let Some(error) = stdout.strip_prefix(CARGO_ERROR_SYNTAX) { + log_messages_in_case_of_panic.push((Severity::Error, error.to_owned())); + } + if let Some(warning) = stdout + .strip_prefix(OLD_CARGO_WARNING_SYNTAX) + .or(stdout.strip_prefix(NEW_CARGO_WARNING_SYNTAX)) + { + log_messages_in_case_of_panic.push((Severity::Warning, warning.to_owned())); + } + if extra_verbose { + state.stdout(format!("{}{}", prefix, stdout))?; + } + Ok(()) + }, + &mut |stderr| { + if extra_verbose { + state.stderr(format!("{}{}", prefix, stderr))?; + } + Ok(()) + }, + true, + ) + .with_context(|| { + let mut build_error_context = + format!("failed to run custom build command for `{}`", pkg_descr); + + // If we're opting into backtraces, mention that build dependencies' backtraces can + // be improved by requesting debuginfo to be built, if we're not building with + // debuginfo already. + // + // ALLOWED: Other tools like `rustc` might read it directly + // through `std::env`. We should make their behavior consistent. + #[allow(clippy::disallowed_methods)] + if let Ok(show_backtraces) = std::env::var("RUST_BACKTRACE") { + if !built_with_debuginfo && show_backtraces != "0" { + build_error_context.push_str(&format!( + "\n\ + note: To improve backtraces for build dependencies, set the \ + CARGO_PROFILE_{env_profile_name}_BUILD_OVERRIDE_DEBUG=true environment \ + variable to enable debug information generation.", + )); + } + } + + build_error_context + }); + + // If the build failed + if let Err(error) = output { + insert_log_messages_in_build_outputs( + build_script_outputs, + id, + metadata_hash, + log_messages_in_case_of_panic, + ); + return Err(error); + } + // ... or it logged any errors + else if log_messages_in_case_of_panic + .iter() + .any(|(severity, _)| *severity == Severity::Error) + { + insert_log_messages_in_build_outputs( + build_script_outputs, + id, + metadata_hash, + log_messages_in_case_of_panic, + ); + anyhow::bail!("build script logged errors"); + } + + let output = output.unwrap(); + + // After the build command has finished running, we need to be sure to + // remember all of its output so we can later discover precisely what it + // was, even if we don't run the build command again (due to freshness). + // + // This is also the location where we provide feedback into the build + // state informing what variables were discovered via our script as + // well. + paths::write(&output_file, &output.stdout)?; + // This mtime shift allows Cargo to detect if a source file was + // modified in the middle of the build. + paths::set_file_time_no_err(output_file, timestamp); + paths::write(&err_file, &output.stderr)?; + paths::write(&root_output_file, paths::path2bytes(&script_out_dir)?)?; + let parsed_output = BuildOutput::parse( + &output.stdout, + library_name, + &pkg_descr, + &script_out_dir, + &script_out_dir, + nightly_features_allowed, + &targets, + &msrv, + )?; + + if json_messages { + emit_build_output(state, &parsed_output, script_out_dir.as_path(), id)?; + } + build_script_outputs + .lock() + .unwrap() + .insert(id, metadata_hash, parsed_output); + Ok(()) + }); + + // Now that we've prepared our work-to-do, we need to prepare the fresh work + // itself to run when we actually end up just discarding what we calculated + // above. + let fresh = Work::new(move |state| { + let (id, library_name, pkg_descr, build_script_outputs, output_file, script_out_dir) = all; + let output = match prev_output { + Some(output) => output, + None => BuildOutput::parse_file( + &output_file, + library_name, + &pkg_descr, + &prev_script_out_dir, + &script_out_dir, + nightly_features_allowed, + &targets_fresh, + &msrv_fresh, + )?, + }; + + if json_messages { + emit_build_output(state, &output, script_out_dir.as_path(), id)?; + } + + build_script_outputs + .lock() + .unwrap() + .insert(id, metadata_hash, output); + Ok(()) + }); + + let mut job = if build_runner.bcx.build_config.build_plan { + Job::new_dirty(Work::noop(), DirtyReason::FreshBuild) + } else { + fingerprint::prepare_target(build_runner, unit, false)? + }; + if job.freshness().is_dirty() { + job.before(dirty); + } else { + job.before(fresh); + } + Ok(job) +} + +/// When a build script run fails, store only log messages, and nuke other +/// outputs, as they are likely broken. +fn insert_log_messages_in_build_outputs( + build_script_outputs: Arc>, + id: PackageId, + metadata_hash: UnitHash, + log_messages: Vec, +) { + let build_output_with_only_log_messages = BuildOutput { + log_messages, + ..BuildOutput::default() + }; + build_script_outputs.lock().unwrap().insert( + id, + metadata_hash, + build_output_with_only_log_messages, + ); +} + +impl BuildOutput { + /// Like [`BuildOutput::parse`] but from a file path. + pub fn parse_file( + path: &Path, + library_name: Option, + pkg_descr: &str, + script_out_dir_when_generated: &Path, + script_out_dir: &Path, + nightly_features_allowed: bool, + targets: &[Target], + msrv: &Option, + ) -> CargoResult { + let contents = paths::read_bytes(path)?; + BuildOutput::parse( + &contents, + library_name, + pkg_descr, + script_out_dir_when_generated, + script_out_dir, + nightly_features_allowed, + targets, + msrv, + ) + } + + /// Parses the output instructions of a build script. + /// + /// * `pkg_descr` --- for error messages + /// * `library_name` --- for determining if `RUSTC_BOOTSTRAP` should be allowed + pub fn parse( + input: &[u8], + // Takes String instead of InternedString so passing `unit.pkg.name()` will give a compile error. + library_name: Option, + pkg_descr: &str, + script_out_dir_when_generated: &Path, + script_out_dir: &Path, + nightly_features_allowed: bool, + targets: &[Target], + msrv: &Option, + ) -> CargoResult { + let mut library_paths = Vec::new(); + let mut library_links = Vec::new(); + let mut linker_args = Vec::new(); + let mut cfgs = Vec::new(); + let mut check_cfgs = Vec::new(); + let mut env = Vec::new(); + let mut metadata = Vec::new(); + let mut rerun_if_changed = Vec::new(); + let mut rerun_if_env_changed = Vec::new(); + let mut log_messages = Vec::new(); + let whence = format!("build script of `{}`", pkg_descr); + // Old syntax: + // cargo:rustc-flags=VALUE + // cargo:KEY=VALUE (for other unreserved keys) + // New syntax: + // cargo::rustc-flags=VALUE + // cargo::metadata=KEY=VALUE (for other unreserved keys) + // Due to backwards compatibility, no new keys can be added to this old format. + const RESERVED_PREFIXES: &[&str] = &[ + "rustc-flags=", + "rustc-link-lib=", + "rustc-link-search=", + "rustc-link-arg-cdylib=", + "rustc-cdylib-link-arg=", + "rustc-link-arg-bins=", + "rustc-link-arg-bin=", + "rustc-link-arg-tests=", + "rustc-link-arg-benches=", + "rustc-link-arg-examples=", + "rustc-link-arg=", + "rustc-cfg=", + "rustc-check-cfg=", + "rustc-env=", + "warning=", + "rerun-if-changed=", + "rerun-if-env-changed=", + ]; + const DOCS_LINK_SUGGESTION: &str = "See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script \ + for more information about build script outputs."; + + fn has_reserved_prefix(flag: &str) -> bool { + RESERVED_PREFIXES + .iter() + .any(|reserved_prefix| flag.starts_with(reserved_prefix)) + } + + fn check_minimum_supported_rust_version_for_new_syntax( + pkg_descr: &str, + msrv: &Option, + flag: &str, + ) -> CargoResult<()> { + if let Some(msrv) = msrv { + let new_syntax_added_in = RustVersion::from_str("1.77.0")?; + if !new_syntax_added_in.is_compatible_with(msrv.as_partial()) { + let old_syntax_suggestion = if has_reserved_prefix(flag) { + format!( + "Switch to the old `cargo:{flag}` syntax (note the single colon).\n" + ) + } else if flag.starts_with("metadata=") { + let old_format_flag = flag.strip_prefix("metadata=").unwrap(); + format!("Switch to the old `cargo:{old_format_flag}` syntax instead of `cargo::{flag}` (note the single colon).\n") + } else { + String::new() + }; + + bail!( + "the `cargo::` syntax for build script output instructions was added in \ + Rust 1.77.0, but the minimum supported Rust version of `{pkg_descr}` is {msrv}.\n\ + {old_syntax_suggestion}\ + {DOCS_LINK_SUGGESTION}" + ); + } + } + + Ok(()) + } + + fn parse_directive<'a>( + whence: &str, + line: &str, + data: &'a str, + old_syntax: bool, + ) -> CargoResult<(&'a str, &'a str)> { + let mut iter = data.splitn(2, "="); + let key = iter.next(); + let value = iter.next(); + match (key, value) { + (Some(a), Some(b)) => Ok((a, b.trim_end())), + _ => bail!( + "invalid output in {whence}: `{line}`\n\ + Expected a line with `{syntax}KEY=VALUE` with an `=` character, \ + but none was found.\n\ + {DOCS_LINK_SUGGESTION}", + syntax = if old_syntax { "cargo:" } else { "cargo::" }, + ), + } + } + + fn parse_metadata<'a>( + whence: &str, + line: &str, + data: &'a str, + old_syntax: bool, + ) -> CargoResult<(&'a str, &'a str)> { + let mut iter = data.splitn(2, "="); + let key = iter.next(); + let value = iter.next(); + match (key, value) { + (Some(a), Some(b)) => Ok((a, b.trim_end())), + _ => bail!( + "invalid output in {whence}: `{line}`\n\ + Expected a line with `{syntax}KEY=VALUE` with an `=` character, \ + but none was found.\n\ + {DOCS_LINK_SUGGESTION}", + syntax = if old_syntax { + "cargo:" + } else { + "cargo::metadata=" + }, + ), + } + } + + for line in input.split(|b| *b == b'\n') { + let line = match str::from_utf8(line) { + Ok(line) => line.trim(), + Err(..) => continue, + }; + let mut old_syntax = false; + let (key, value) = if let Some(data) = line.strip_prefix("cargo::") { + check_minimum_supported_rust_version_for_new_syntax(pkg_descr, msrv, data)?; + // For instance, `cargo::rustc-flags=foo` or `cargo::metadata=foo=bar`. + parse_directive(whence.as_str(), line, data, old_syntax)? + } else if let Some(data) = line.strip_prefix("cargo:") { + old_syntax = true; + // For instance, `cargo:rustc-flags=foo`. + if has_reserved_prefix(data) { + parse_directive(whence.as_str(), line, data, old_syntax)? + } else { + // For instance, `cargo:foo=bar`. + ("metadata", data) + } + } else { + // Skip this line since it doesn't start with "cargo:" or "cargo::". + continue; + }; + // This will rewrite paths if the target directory has been moved. + let value = value.replace( + script_out_dir_when_generated.to_str().unwrap(), + script_out_dir.to_str().unwrap(), + ); + + let syntax_prefix = if old_syntax { "cargo:" } else { "cargo::" }; + macro_rules! check_and_add_target { + ($target_kind: expr, $is_target_kind: expr, $link_type: expr) => { + if !targets.iter().any(|target| $is_target_kind(target)) { + bail!( + "invalid instruction `{}{}` from {}\n\ + The package {} does not have a {} target.", + syntax_prefix, + key, + whence, + pkg_descr, + $target_kind + ); + } + linker_args.push(($link_type, value)); + }; + } + + // Keep in sync with TargetConfig::parse_links_overrides. + match key { + "rustc-flags" => { + let (paths, links) = BuildOutput::parse_rustc_flags(&value, &whence)?; + library_links.extend(links.into_iter()); + library_paths.extend(paths.into_iter()); + } + "rustc-link-lib" => library_links.push(value.to_string()), + "rustc-link-search" => library_paths.push(PathBuf::from(value)), + "rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => { + if !targets.iter().any(|target| target.is_cdylib()) { + log_messages.push(( + Severity::Warning, + format!( + "{}{} was specified in the build script of {}, \ + but that package does not contain a cdylib target\n\ + \n\ + Allowing this was an unintended change in the 1.50 \ + release, and may become an error in the future. \ + For more information, see \ + .", + syntax_prefix, key, pkg_descr + ), + )); + } + linker_args.push((LinkArgTarget::Cdylib, value)) + } + "rustc-link-arg-bins" => { + check_and_add_target!("bin", Target::is_bin, LinkArgTarget::Bin); + } + "rustc-link-arg-bin" => { + let (bin_name, arg) = value.split_once('=').ok_or_else(|| { + anyhow::format_err!( + "invalid instruction `{}{}={}` from {}\n\ + The instruction should have the form {}{}=BIN=ARG", + syntax_prefix, + key, + value, + whence, + syntax_prefix, + key + ) + })?; + if !targets + .iter() + .any(|target| target.is_bin() && target.name() == bin_name) + { + bail!( + "invalid instruction `{}{}` from {}\n\ + The package {} does not have a bin target with the name `{}`.", + syntax_prefix, + key, + whence, + pkg_descr, + bin_name + ); + } + 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); + } + "rustc-link-arg-benches" => { + check_and_add_target!("benchmark", Target::is_bench, LinkArgTarget::Bench); + } + "rustc-link-arg-examples" => { + check_and_add_target!("example", Target::is_example, LinkArgTarget::Example); + } + "rustc-link-arg" => { + linker_args.push((LinkArgTarget::All, value)); + } + "rustc-cfg" => cfgs.push(value.to_string()), + "rustc-check-cfg" => check_cfgs.push(value.to_string()), + "rustc-env" => { + let (key, val) = BuildOutput::parse_rustc_env(&value, &whence)?; + // Build scripts aren't allowed to set RUSTC_BOOTSTRAP. + // See https://github.com/rust-lang/cargo/issues/7088. + if key == "RUSTC_BOOTSTRAP" { + // If RUSTC_BOOTSTRAP is already set, the user of Cargo knows about + // bootstrap and still wants to override the channel. Give them a way to do + // so, but still emit a warning that the current crate shouldn't be trying + // to set RUSTC_BOOTSTRAP. + // If this is a nightly build, setting RUSTC_BOOTSTRAP wouldn't affect the + // behavior, so still only give a warning. + // NOTE: cargo only allows nightly features on RUSTC_BOOTSTRAP=1, but we + // want setting any value of RUSTC_BOOTSTRAP to downgrade this to a warning + // (so that `RUSTC_BOOTSTRAP=library_name` will work) + let rustc_bootstrap_allows = |name: Option<&str>| { + let name = match name { + // as of 2021, no binaries on crates.io use RUSTC_BOOTSTRAP, so + // fine-grained opt-outs aren't needed. end-users can always use + // RUSTC_BOOTSTRAP=1 from the top-level if it's really a problem. + None => return false, + Some(n) => n, + }; + // 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)] + std::env::var("RUSTC_BOOTSTRAP") + .map_or(false, |var| var.split(',').any(|s| s == name)) + }; + if nightly_features_allowed + || rustc_bootstrap_allows(library_name.as_deref()) + { + log_messages.push((Severity::Warning, format!("Cannot set `RUSTC_BOOTSTRAP={}` from {}.\n\ + note: Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.", + val, whence + ))); + } else { + // Setting RUSTC_BOOTSTRAP would change the behavior of the crate. + // Abort with an error. + bail!("Cannot set `RUSTC_BOOTSTRAP={}` from {}.\n\ + note: Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n\ + help: If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP={}` before running cargo instead.", + val, + whence, + library_name.as_deref().unwrap_or("1"), + ); + } + } else { + env.push((key, val)); + } + } + "error" => log_messages.push((Severity::Error, value.to_string())), + "warning" => log_messages.push((Severity::Warning, value.to_string())), + "rerun-if-changed" => rerun_if_changed.push(PathBuf::from(value)), + "rerun-if-env-changed" => rerun_if_env_changed.push(value.to_string()), + "metadata" => { + let (key, value) = parse_metadata(whence.as_str(), line, &value, old_syntax)?; + metadata.push((key.to_owned(), value.to_owned())); + } + _ => bail!( + "invalid output in {whence}: `{line}`\n\ + Unknown key: `{key}`.\n\ + {DOCS_LINK_SUGGESTION}", + ), + } + } + + Ok(BuildOutput { + library_paths, + library_links, + linker_args, + cfgs, + check_cfgs, + env, + metadata, + rerun_if_changed, + rerun_if_env_changed, + log_messages, + }) + } + + /// Parses [`cargo::rustc-flags`] instruction. + /// + /// [`cargo::rustc-flags`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#cargorustc-flagsflags + pub fn parse_rustc_flags( + value: &str, + whence: &str, + ) -> CargoResult<(Vec, Vec)> { + let value = value.trim(); + let mut flags_iter = value + .split(|c: char| c.is_whitespace()) + .filter(|w| w.chars().any(|c| !c.is_whitespace())); + let (mut library_paths, mut library_links) = (Vec::new(), Vec::new()); + + while let Some(flag) = flags_iter.next() { + if flag.starts_with("-l") || flag.starts_with("-L") { + // Check if this flag has no space before the value as is + // common with tools like pkg-config + // e.g. -L/some/dir/local/lib or -licui18n + let (flag, mut value) = flag.split_at(2); + if value.is_empty() { + value = match flags_iter.next() { + Some(v) => v, + None => bail! { + "Flag in rustc-flags has no value in {}: {}", + whence, + value + }, + } + } + + match flag { + "-l" => library_links.push(value.to_string()), + "-L" => library_paths.push(PathBuf::from(value)), + + // This was already checked above + _ => unreachable!(), + }; + } else { + bail!( + "Only `-l` and `-L` flags are allowed in {}: `{}`", + whence, + value + ) + } + } + Ok((library_paths, library_links)) + } + + /// Parses [`cargo::rustc-env`] instruction. + /// + /// [`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)> { + match value.split_once('=') { + Some((n, v)) => Ok((n.to_owned(), v.to_owned())), + _ => bail!("Variable rustc-env has no value in {whence}: {value}"), + } + } +} + +/// Prepares the Rust script for the unstable feature [metabuild]. +/// +/// [metabuild]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#metabuild +fn prepare_metabuild( + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + deps: &[String], +) -> CargoResult<()> { + let mut output = Vec::new(); + let available_deps = build_runner.unit_deps(unit); + // Filter out optional dependencies, and look up the actual lib name. + let meta_deps: Vec<_> = deps + .iter() + .filter_map(|name| { + available_deps + .iter() + .find(|d| d.unit.pkg.name().as_str() == name.as_str()) + .map(|d| d.unit.target.crate_name()) + }) + .collect(); + output.push("fn main() {\n".to_string()); + for dep in &meta_deps { + output.push(format!(" {}::metabuild();\n", dep)); + } + output.push("}\n".to_string()); + let output = output.join(""); + let path = unit + .pkg + .manifest() + .metabuild_path(build_runner.bcx.ws.target_dir()); + paths::create_dir_all(path.parent().unwrap())?; + paths::write_if_changed(path, &output)?; + Ok(()) +} + +impl BuildDeps { + /// Creates a build script dependency information from a previous + /// build script output path and the content. + pub fn new(output_file: &Path, output: Option<&BuildOutput>) -> BuildDeps { + BuildDeps { + build_script_output: output_file.to_path_buf(), + rerun_if_changed: output + .map(|p| &p.rerun_if_changed) + .cloned() + .unwrap_or_default(), + rerun_if_env_changed: output + .map(|p| &p.rerun_if_env_changed) + .cloned() + .unwrap_or_default(), + } + } +} + +/// Computes several maps in [`BuildRunner`]. +/// +/// - [`build_scripts`]: A map that tracks which build scripts each package +/// depends on. +/// - [`build_explicit_deps`]: Dependency statements emitted by build scripts +/// from a previous run. +/// - [`build_script_outputs`]: Pre-populates this with any overridden build +/// scripts. +/// +/// The important one here is [`build_scripts`], which for each `(package, +/// metadata)` stores a [`BuildScripts`] object which contains a list of +/// dependencies with build scripts that the unit should consider when linking. +/// For example this lists all dependencies' `-L` flags which need to be +/// propagated transitively. +/// +/// The given set of units to this function is the initial set of +/// targets/profiles which are being built. +/// +/// [`build_scripts`]: BuildRunner::build_scripts +/// [`build_explicit_deps`]: BuildRunner::build_explicit_deps +/// [`build_script_outputs`]: BuildRunner::build_script_outputs +pub fn build_map(build_runner: &mut BuildRunner<'_, '_>) -> CargoResult<()> { + let mut ret = HashMap::new(); + for unit in &build_runner.bcx.roots { + build(&mut ret, build_runner, unit)?; + } + build_runner + .build_scripts + .extend(ret.into_iter().map(|(k, v)| (k, Arc::new(v)))); + return Ok(()); + + // Recursive function to build up the map we're constructing. This function + // memoizes all of its return values as it goes along. + fn build<'a>( + out: &'a mut HashMap, + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, + ) -> CargoResult<&'a BuildScripts> { + // Do a quick pre-flight check to see if we've already calculated the + // set of dependencies. + if out.contains_key(unit) { + return Ok(&out[unit]); + } + + // If there is a build script override, pre-fill the build output. + if unit.mode.is_run_custom_build() { + if let Some(links) = unit.pkg.manifest().links() { + if let Some(output) = unit.links_overrides.get(links) { + let metadata = build_runner.get_run_build_script_metadata(unit); + build_runner.build_script_outputs.lock().unwrap().insert( + unit.pkg.package_id(), + metadata, + output.clone(), + ); + } + } + } + + let mut ret = BuildScripts::default(); + + // If a package has a build script, add itself as something to inspect for linking. + if !unit.target.is_custom_build() && unit.pkg.has_custom_build() { + let script_meta = build_runner + .find_build_script_metadata(unit) + .expect("has_custom_build should have RunCustomBuild"); + add_to_link(&mut ret, unit.pkg.package_id(), script_meta); + } + + if unit.mode.is_run_custom_build() { + parse_previous_explicit_deps(build_runner, unit); + } + + // We want to invoke the compiler deterministically to be cache-friendly + // to rustc invocation caching schemes, so be sure to generate the same + // set of build script dependency orderings via sorting the targets that + // come out of the `Context`. + let mut dependencies: Vec = build_runner + .unit_deps(unit) + .iter() + .map(|d| d.unit.clone()) + .collect(); + dependencies.sort_by_key(|u| u.pkg.package_id()); + + for dep_unit in dependencies.iter() { + let dep_scripts = build(out, build_runner, dep_unit)?; + + if dep_unit.target.for_host() { + ret.plugins.extend(dep_scripts.to_link.iter().cloned()); + } else if dep_unit.target.is_linkable() { + for &(pkg, metadata) in dep_scripts.to_link.iter() { + add_to_link(&mut ret, pkg, metadata); + } + } + } + + match out.entry(unit.clone()) { + Entry::Vacant(entry) => Ok(entry.insert(ret)), + Entry::Occupied(_) => panic!("cyclic dependencies in `build_map`"), + } + } + + // When adding an entry to 'to_link' we only actually push it on if the + // script hasn't seen it yet (e.g., we don't push on duplicates). + fn add_to_link(scripts: &mut BuildScripts, pkg: PackageId, metadata: UnitHash) { + if scripts.seen_to_link.insert((pkg, metadata)) { + scripts.to_link.push((pkg, metadata)); + } + } + + /// Load any dependency declarations from a previous build script run. + fn parse_previous_explicit_deps(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) { + let script_run_dir = build_runner.files().build_script_run_dir(unit); + let output_file = script_run_dir.join("output"); + let (prev_output, _) = prev_build_output(build_runner, unit); + let deps = BuildDeps::new(&output_file, prev_output.as_ref()); + build_runner.build_explicit_deps.insert(unit.clone(), deps); + } +} + +/// Returns the previous parsed `BuildOutput`, if any, from a previous +/// execution. +/// +/// Also returns the directory containing the output, typically used later in +/// processing. +fn prev_build_output( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, +) -> (Option, PathBuf) { + let script_out_dir = build_runner.files().build_script_out_dir(unit); + let script_run_dir = build_runner.files().build_script_run_dir(unit); + let root_output_file = script_run_dir.join("root-output"); + let output_file = script_run_dir.join("output"); + + let prev_script_out_dir = paths::read_bytes(&root_output_file) + .and_then(|bytes| paths::bytes2path(&bytes)) + .unwrap_or_else(|_| script_out_dir.clone()); + + ( + BuildOutput::parse_file( + &output_file, + unit.pkg.library().map(|t| t.crate_name()), + &unit.pkg.to_string(), + &prev_script_out_dir, + &script_out_dir, + build_runner.bcx.gctx.nightly_features_allowed, + unit.pkg.targets(), + &unit.pkg.rust_version().cloned(), + ) + .ok(), + prev_script_out_dir, + ) +} + +impl BuildScriptOutputs { + /// Inserts a new entry into the map. + fn insert(&mut self, pkg_id: PackageId, metadata: UnitHash, parsed_output: BuildOutput) { + match self.outputs.entry(metadata) { + Entry::Vacant(entry) => { + entry.insert(parsed_output); + } + Entry::Occupied(entry) => panic!( + "build script output collision for {}/{}\n\ + old={:?}\nnew={:?}", + pkg_id, + metadata, + entry.get(), + parsed_output + ), + } + } + + /// Returns `true` if the given key already exists. + fn contains_key(&self, metadata: UnitHash) -> bool { + self.outputs.contains_key(&metadata) + } + + /// Gets the build output for the given key. + pub fn get(&self, meta: UnitHash) -> Option<&BuildOutput> { + self.outputs.get(&meta) + } + + /// Returns an iterator over all entries. + pub fn iter(&self) -> impl Iterator { + self.outputs.iter() + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dep_info.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dep_info.rs new file mode 100644 index 000000000..746c08320 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dep_info.rs @@ -0,0 +1,762 @@ +//! Types and functions managing dep-info files. +//! For more, see [the documentation] in the `fingerprint` module. +//! +//! [the documentation]: crate::core::compiler::fingerprint#dep-info-files + +use std::collections::HashMap; +use std::ffi::OsString; +use std::fmt; +use std::io; +use std::io::Read; +use std::path::Path; +use std::path::PathBuf; +use std::str; +use std::str::FromStr; +use std::sync::Arc; + +use anyhow::bail; +use cargo_util::paths; +use cargo_util::ProcessBuilder; +use cargo_util::Sha256; + +use crate::core::manifest::ManifestMetadata; +use crate::CargoResult; +use crate::CARGO_ENV; + +/// The current format version of [`EncodedDepInfo`]. +const CURRENT_ENCODED_DEP_INFO_VERSION: u8 = 1; + +/// The representation of the `.d` dep-info file generated by rustc +#[derive(Default)] +pub struct RustcDepInfo { + /// The list of files that the main target in the dep-info file depends on. + /// + /// The optional checksums are parsed from the special `# checksum:...` comments. + pub files: HashMap>, + /// The list of environment variables we found that the rustc compilation + /// depends on. + /// + /// The first element of the pair is the name of the env var and the second + /// item is the value. `Some` means that the env var was set, and `None` + /// means that the env var wasn't actually set and the compilation depends + /// on it not being set. + /// + /// These are from the special `# env-var:...` comments. + pub env: Vec<(String, Option)>, +} + +/// Tells the associated path in [`EncodedDepInfo::files`] is relative to package root, +/// target root, or absolute. +#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)] +pub enum DepInfoPathType { + /// src/, e.g. src/lib.rs + PackageRootRelative, + /// target/debug/deps/lib... + /// or an absolute path /.../sysroot/... + TargetRootRelative, +} + +/// Same as [`RustcDepInfo`] except avoids absolute paths as much as possible to +/// allow moving around the target directory. +/// +/// This is also stored in an optimized format to make parsing it fast because +/// Cargo will read it for crates on all future compilations. +/// +/// Currently the format looks like: +/// +/// ```text +/// +--------+---------+------------+------------+---------------+---------------+ +/// | marker | version | # of files | file paths | # of env vars | env var pairs | +/// +--------+---------+------------+------------+---------------+---------------+ +/// ``` +/// +/// Each field represents +/// +/// * _Marker_ --- A magic marker to ensure that older Cargoes, which only +/// recognize format v0 (prior to checksum support in [`f4ca7390`]), do not +/// proceed with parsing newer formats. Since [`EncodedDepInfo`] is merely +/// an optimization, and to avoid adding complexity, Cargo recognizes only +/// one version of [`CURRENT_ENCODED_DEP_INFO_VERSION`]. +/// The current layout looks like this +/// ```text +/// +----------------------------+ +/// | [0x01 0x00 0x00 0x00 0xff] | +/// +----------------------------+ +/// ``` +/// These bytes will be interpreted as "one file tracked and an invalid +/// [`DepInfoPathType`] variant with 255" by older Cargoes, causing them to +/// stop parsing. This could prevent problematic parsing as noted in +/// rust-lang/cargo#14712. +/// * _Version_ --- The current format version. +/// * _Number of files/envs_ --- A `u32` representing the number of things. +/// * _File paths_ --- Zero or more paths of files the dep-info file depends on. +/// Each path is encoded as the following: +/// +/// ```text +/// +-----------+-------------+------------+---------------+-----------+-------+ +/// | path type | len of path | path bytes | cksum exists? | file size | cksum | +/// +-----------+-------------+------------+---------------+-----------+-------+ +/// ``` +/// * _Env var pairs_ --- Zero or more env vars the dep-info file depends on. +/// Each env key-value pair is encoded as the following: +/// ```text +/// +------------+-----------+---------------+--------------+-------------+ +/// | len of key | key bytes | value exists? | len of value | value bytes | +/// +------------+-----------+---------------+--------------+-------------+ +/// ``` +/// +/// [`f4ca7390`]: https://github.com/rust-lang/cargo/commit/f4ca739073185ea5e1148ff100bb4a06d3bf721d +#[derive(Default, Debug, PartialEq, Eq)] +pub struct EncodedDepInfo { + pub files: Vec<(DepInfoPathType, PathBuf, Option<(u64, String)>)>, + pub env: Vec<(String, Option)>, +} + +impl EncodedDepInfo { + pub fn parse(mut bytes: &[u8]) -> Option { + let bytes = &mut bytes; + read_magic_marker(bytes)?; + let version = read_u8(bytes)?; + if version != CURRENT_ENCODED_DEP_INFO_VERSION { + return None; + } + + let nfiles = read_usize(bytes)?; + let mut files = Vec::with_capacity(nfiles); + for _ in 0..nfiles { + let ty = match read_u8(bytes)? { + 0 => DepInfoPathType::PackageRootRelative, + 1 => DepInfoPathType::TargetRootRelative, + _ => return None, + }; + let path_bytes = read_bytes(bytes)?; + let path = paths::bytes2path(path_bytes).ok()?; + let has_checksum = read_bool(bytes)?; + let checksum_info = has_checksum + .then(|| { + let file_len = read_u64(bytes); + let checksum_string = read_bytes(bytes) + .map(Vec::from) + .and_then(|v| String::from_utf8(v).ok()); + file_len.zip(checksum_string) + }) + .flatten(); + files.push((ty, path, checksum_info)); + } + + let nenv = read_usize(bytes)?; + let mut env = Vec::with_capacity(nenv); + for _ in 0..nenv { + let key = str::from_utf8(read_bytes(bytes)?).ok()?.to_string(); + let val = match read_u8(bytes)? { + 0 => None, + 1 => Some(str::from_utf8(read_bytes(bytes)?).ok()?.to_string()), + _ => return None, + }; + env.push((key, val)); + } + return Some(EncodedDepInfo { files, env }); + + /// See [`EncodedDepInfo`] for why a magic marker exists. + fn read_magic_marker(bytes: &mut &[u8]) -> Option<()> { + let _size = read_usize(bytes)?; + let path_type = read_u8(bytes)?; + if path_type != u8::MAX { + // Old depinfo. Give up parsing it. + None + } else { + Some(()) + } + } + + fn read_usize(bytes: &mut &[u8]) -> Option { + let ret = bytes.get(..4)?; + *bytes = &bytes[4..]; + Some(u32::from_le_bytes(ret.try_into().unwrap()) as usize) + } + + fn read_u64(bytes: &mut &[u8]) -> Option { + let ret = bytes.get(..8)?; + *bytes = &bytes[8..]; + Some(u64::from_le_bytes(ret.try_into().unwrap())) + } + + fn read_bool(bytes: &mut &[u8]) -> Option { + read_u8(bytes).map(|b| b != 0) + } + + fn read_u8(bytes: &mut &[u8]) -> Option { + let ret = *bytes.get(0)?; + *bytes = &bytes[1..]; + Some(ret) + } + + fn read_bytes<'a>(bytes: &mut &'a [u8]) -> Option<&'a [u8]> { + let n = read_usize(bytes)? as usize; + let ret = bytes.get(..n)?; + *bytes = &bytes[n..]; + Some(ret) + } + } + + pub fn serialize(&self) -> CargoResult> { + let mut ret = Vec::new(); + let dst = &mut ret; + + write_magic_marker(dst); + dst.push(CURRENT_ENCODED_DEP_INFO_VERSION); + + write_usize(dst, self.files.len()); + for (ty, file, checksum_info) in self.files.iter() { + match ty { + DepInfoPathType::PackageRootRelative => dst.push(0), + DepInfoPathType::TargetRootRelative => dst.push(1), + } + write_bytes(dst, paths::path2bytes(file)?); + write_bool(dst, checksum_info.is_some()); + if let Some((len, checksum)) = checksum_info { + write_u64(dst, *len); + write_bytes(dst, checksum); + } + } + + write_usize(dst, self.env.len()); + for (key, val) in self.env.iter() { + write_bytes(dst, key); + match val { + None => dst.push(0), + Some(val) => { + dst.push(1); + write_bytes(dst, val); + } + } + } + return Ok(ret); + + /// See [`EncodedDepInfo`] for why a magic marker exists. + /// + /// There is an assumption that there is always at least a file. + fn write_magic_marker(dst: &mut Vec) { + write_usize(dst, 1); + dst.push(u8::MAX); + } + + fn write_bytes(dst: &mut Vec, val: impl AsRef<[u8]>) { + let val = val.as_ref(); + write_usize(dst, val.len()); + dst.extend_from_slice(val); + } + + fn write_usize(dst: &mut Vec, val: usize) { + dst.extend(&u32::to_le_bytes(val as u32)); + } + + fn write_u64(dst: &mut Vec, val: u64) { + dst.extend(&u64::to_le_bytes(val)); + } + + fn write_bool(dst: &mut Vec, val: bool) { + dst.push(u8::from(val)); + } + } +} + +/// Parses the dep-info file coming out of rustc into a Cargo-specific format. +/// +/// This function will parse `rustc_dep_info` as a makefile-style dep info to +/// learn about the all files which a crate depends on. This is then +/// re-serialized into the `cargo_dep_info` path in a Cargo-specific format. +/// +/// The `pkg_root` argument here is the absolute path to the directory +/// containing `Cargo.toml` for this crate that was compiled. The paths listed +/// in the rustc dep-info file may or may not be absolute but we'll want to +/// consider all of them relative to the `root` specified. +/// +/// The `rustc_cwd` argument is the absolute path to the cwd of the compiler +/// when it was invoked. +/// +/// If the `allow_package` argument is true, then package-relative paths are +/// included. If it is false, then package-relative paths are skipped and +/// ignored (typically used for registry or git dependencies where we assume +/// the source never changes, and we don't want the cost of running `stat` on +/// all those files). See the module-level docs for the note about +/// `-Zbinary-dep-depinfo` for more details on why this is done. +/// +/// The serialized Cargo format will contain a list of files, all of which are +/// relative if they're under `root`. or absolute if they're elsewhere. +/// +/// The `env_config` argument is a set of environment variables that are +/// defined in `[env]` table of the `config.toml`. +pub fn translate_dep_info( + rustc_dep_info: &Path, + cargo_dep_info: &Path, + rustc_cwd: &Path, + pkg_root: &Path, + target_root: &Path, + rustc_cmd: &ProcessBuilder, + allow_package: bool, + env_config: &Arc>, +) -> CargoResult<()> { + let depinfo = parse_rustc_dep_info(rustc_dep_info)?; + + let target_root = crate::util::try_canonicalize(target_root)?; + let pkg_root = crate::util::try_canonicalize(pkg_root)?; + let mut on_disk_info = EncodedDepInfo::default(); + on_disk_info.env = depinfo.env; + + // This is a bit of a tricky statement, but here we're *removing* the + // dependency on environment variables that were defined specifically for + // the command itself. Environment variables returned by `get_envs` includes + // environment variables like: + // + // * `OUT_DIR` if applicable + // * env vars added by a build script, if any + // + // The general idea here is that the dep info file tells us what, when + // changed, should cause us to rebuild the crate. These environment + // variables are synthesized by Cargo and/or the build script, and the + // intention is that their values are tracked elsewhere for whether the + // crate needs to be rebuilt. + // + // For example a build script says when it needs to be rerun and otherwise + // it's assumed to produce the same output, so we're guaranteed that env + // vars defined by the build script will always be the same unless the build + // script itself reruns, in which case the crate will rerun anyway. + // + // For things like `OUT_DIR` it's a bit sketchy for now. Most of the time + // that's used for code generation but this is technically buggy where if + // you write a binary that does `println!("{}", env!("OUT_DIR"))` we won't + // recompile that if you move the target directory. Hopefully that's not too + // bad of an issue for now... + // + // This also includes `CARGO` since if the code is explicitly wanting to + // know that path, it should be rebuilt if it changes. The CARGO path is + // not tracked elsewhere in the fingerprint. + // + // For cargo#13280, We trace env vars that are defined in the `[env]` config table. + on_disk_info.env.retain(|(key, _)| { + ManifestMetadata::should_track(key) + || env_config.contains_key(key) + || !rustc_cmd.get_envs().contains_key(key) + || key == CARGO_ENV + }); + + let serialize_path = |file| { + // The path may be absolute or relative, canonical or not. Make sure + // it is canonicalized so we are comparing the same kinds of paths. + let abs_file = rustc_cwd.join(file); + // If canonicalization fails, just use the abs path. There is currently + // a bug where --remap-path-prefix is affecting .d files, causing them + // to point to non-existent paths. + let canon_file = + crate::util::try_canonicalize(&abs_file).unwrap_or_else(|_| abs_file.clone()); + + let (ty, path) = if let Ok(stripped) = canon_file.strip_prefix(&target_root) { + (DepInfoPathType::TargetRootRelative, stripped) + } else if let Ok(stripped) = canon_file.strip_prefix(&pkg_root) { + if !allow_package { + return None; + } + (DepInfoPathType::PackageRootRelative, stripped) + } else { + // It's definitely not target root relative, but this is an absolute path (since it was + // joined to rustc_cwd) and as such re-joining it later to the target root will have no + // effect. + (DepInfoPathType::TargetRootRelative, &*abs_file) + }; + Some((ty, path.to_owned())) + }; + + for (file, checksum_info) in depinfo.files { + let Some((path_type, path)) = serialize_path(file) else { + continue; + }; + on_disk_info.files.push(( + path_type, + path, + checksum_info.map(|(len, checksum)| (len, checksum.to_string())), + )); + } + paths::write(cargo_dep_info, on_disk_info.serialize()?)?; + Ok(()) +} + +/// Parse the `.d` dep-info file generated by rustc. +pub fn parse_rustc_dep_info(rustc_dep_info: &Path) -> CargoResult { + let contents = paths::read(rustc_dep_info)?; + let mut ret = RustcDepInfo::default(); + let mut found_deps = false; + + for line in contents.lines() { + if let Some(rest) = line.strip_prefix("# env-dep:") { + let mut parts = rest.splitn(2, '='); + let Some(env_var) = parts.next() else { + continue; + }; + let env_val = match parts.next() { + Some(s) => Some(unescape_env(s)?), + None => None, + }; + ret.env.push((unescape_env(env_var)?, env_val)); + } else if let Some(pos) = line.find(": ") { + if found_deps { + continue; + } + found_deps = true; + let mut deps = line[pos + 2..].split_whitespace(); + + while let Some(s) = deps.next() { + let mut file = s.to_string(); + while file.ends_with('\\') { + file.pop(); + file.push(' '); + file.push_str(deps.next().ok_or_else(|| { + crate::util::internal("malformed dep-info format, trailing \\") + })?); + } + ret.files.entry(file.into()).or_default(); + } + } else if let Some(rest) = line.strip_prefix("# checksum:") { + let mut parts = rest.splitn(3, ' '); + let Some(checksum) = parts.next().map(Checksum::from_str).transpose()? else { + continue; + }; + let Some(Ok(file_len)) = parts + .next() + .and_then(|s| s.strip_prefix("file_len:").map(|s| s.parse::())) + else { + continue; + }; + let Some(path) = parts.next().map(PathBuf::from) else { + continue; + }; + + ret.files.insert(path, Some((file_len, checksum))); + } + } + return Ok(ret); + + // rustc tries to fit env var names and values all on a single line, which + // means it needs to escape `\r` and `\n`. The escape syntax used is "\n" + // which means that `\` also needs to be escaped. + fn unescape_env(s: &str) -> CargoResult { + let mut ret = String::with_capacity(s.len()); + let mut chars = s.chars(); + while let Some(c) = chars.next() { + if c != '\\' { + ret.push(c); + continue; + } + match chars.next() { + Some('\\') => ret.push('\\'), + Some('n') => ret.push('\n'), + Some('r') => ret.push('\r'), + Some(c) => bail!("unknown escape character `{}`", c), + None => bail!("unterminated escape character"), + } + } + Ok(ret) + } +} + +/// Parses Cargo's internal [`EncodedDepInfo`] structure that was previously +/// serialized to disk. +/// +/// Note that this is not rustc's `*.d` files. +/// +/// Also note that rustc's `*.d` files are translated to Cargo-specific +/// `EncodedDepInfo` files after compilations have finished in +/// [`translate_dep_info`]. +/// +/// Returns `None` if the file is corrupt or couldn't be read from disk. This +/// indicates that the crate should likely be rebuilt. +pub fn parse_dep_info( + pkg_root: &Path, + target_root: &Path, + dep_info: &Path, +) -> CargoResult> { + let Ok(data) = paths::read_bytes(dep_info) else { + 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; + ret.files + .extend(info.files.into_iter().map(|(ty, path, checksum_info)| { + ( + make_absolute_path(ty, pkg_root, target_root, path), + checksum_info.and_then(|(file_len, checksum)| { + Checksum::from_str(&checksum).ok().map(|c| (file_len, c)) + }), + ) + })); + Ok(Some(ret)) +} + +fn make_absolute_path( + ty: DepInfoPathType, + pkg_root: &Path, + target_root: &Path, + path: PathBuf, +) -> PathBuf { + match ty { + DepInfoPathType::PackageRootRelative => pkg_root.join(path), + // N.B. path might be absolute here in which case the join will have no effect + DepInfoPathType::TargetRootRelative => target_root.join(path), + } +} + +/// Some algorithms are here to ensure compatibility with possible rustc outputs. +/// The presence of an algorithm here is not a suggestion that it's fit for use. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum ChecksumAlgo { + Sha256, + Blake3, +} + +impl ChecksumAlgo { + fn hash_len(&self) -> usize { + match self { + ChecksumAlgo::Sha256 | ChecksumAlgo::Blake3 => 32, + } + } +} + +impl FromStr for ChecksumAlgo { + type Err = InvalidChecksum; + + fn from_str(s: &str) -> Result { + match s { + "sha256" => Ok(Self::Sha256), + "blake3" => Ok(Self::Blake3), + _ => Err(InvalidChecksum::InvalidChecksumAlgo), + } + } +} + +impl fmt::Display for ChecksumAlgo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + ChecksumAlgo::Sha256 => "sha256", + ChecksumAlgo::Blake3 => "blake3", + }) + } +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct Checksum { + algo: ChecksumAlgo, + /// If the algorithm uses fewer than 32 bytes, then the remaining bytes will be zero. + value: [u8; 32], +} + +impl Checksum { + pub fn new(algo: ChecksumAlgo, value: [u8; 32]) -> Self { + Self { algo, value } + } + + pub fn compute(algo: ChecksumAlgo, contents: impl Read) -> Result { + // Buffer size is the recommended amount to fully leverage SIMD instructions on AVX-512 as per + // blake3 documentation. + let mut buf = vec![0; 16 * 1024]; + let mut ret = Self { + algo, + value: [0; 32], + }; + let len = algo.hash_len(); + let value = &mut ret.value[..len]; + + fn digest( + mut hasher: T, + mut update: impl FnMut(&mut T, &[u8]), + finish: impl FnOnce(T, &mut [u8]), + mut contents: impl Read, + buf: &mut [u8], + value: &mut [u8], + ) -> Result<(), io::Error> { + loop { + let bytes_read = contents.read(buf)?; + if bytes_read == 0 { + break; + } + update(&mut hasher, &buf[0..bytes_read]); + } + finish(hasher, value); + Ok(()) + } + + match algo { + ChecksumAlgo::Sha256 => { + digest( + Sha256::new(), + |h, b| { + h.update(b); + }, + |mut h, out| out.copy_from_slice(&h.finish()), + contents, + &mut buf, + value, + )?; + } + ChecksumAlgo::Blake3 => { + digest( + blake3::Hasher::new(), + |h, b| { + h.update(b); + }, + |h, out| out.copy_from_slice(h.finalize().as_bytes()), + contents, + &mut buf, + value, + )?; + } + } + Ok(ret) + } + + pub fn algo(&self) -> ChecksumAlgo { + self.algo + } + + pub fn value(&self) -> &[u8; 32] { + &self.value + } +} + +impl FromStr for Checksum { + type Err = InvalidChecksum; + + fn from_str(s: &str) -> Result { + let mut parts = s.split('='); + let Some(algo) = parts.next().map(ChecksumAlgo::from_str).transpose()? else { + return Err(InvalidChecksum::InvalidFormat); + }; + let Some(checksum) = parts.next() else { + return Err(InvalidChecksum::InvalidFormat); + }; + let mut value = [0; 32]; + if hex::decode_to_slice(checksum, &mut value[0..algo.hash_len()]).is_err() { + return Err(InvalidChecksum::InvalidChecksum(algo)); + } + Ok(Self { algo, value }) + } +} + +impl fmt::Display for Checksum { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut checksum = [0; 64]; + let hash_len = self.algo.hash_len(); + hex::encode_to_slice(&self.value[0..hash_len], &mut checksum[0..(hash_len * 2)]) + .map_err(|_| fmt::Error)?; + write!( + f, + "{}={}", + self.algo, + str::from_utf8(&checksum[0..(hash_len * 2)]).unwrap_or_default() + ) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum InvalidChecksum { + #[error("algorithm portion incorrect, expected `sha256`, or `blake3`")] + InvalidChecksumAlgo, + #[error("expected {} hexadecimal digits in checksum portion", .0.hash_len() * 2)] + InvalidChecksum(ChecksumAlgo), + #[error("expected a string with format \"algorithm=hex_checksum\"")] + InvalidFormat, +} + +#[cfg(test)] +mod encoded_dep_info { + use super::*; + + #[track_caller] + fn gen_test(checksum: bool) { + let checksum = checksum.then_some((768, "c01efc669f09508b55eced32d3c88702578a7c3e".into())); + let lib_rs = ( + DepInfoPathType::TargetRootRelative, + PathBuf::from("src/lib.rs"), + checksum.clone(), + ); + + let depinfo = EncodedDepInfo { + files: vec![lib_rs.clone()], + env: Vec::new(), + }; + let data = depinfo.serialize().unwrap(); + assert_eq!(EncodedDepInfo::parse(&data).unwrap(), depinfo); + + let mod_rs = ( + DepInfoPathType::TargetRootRelative, + PathBuf::from("src/mod.rs"), + checksum.clone(), + ); + let depinfo = EncodedDepInfo { + files: vec![lib_rs.clone(), mod_rs.clone()], + env: Vec::new(), + }; + let data = depinfo.serialize().unwrap(); + assert_eq!(EncodedDepInfo::parse(&data).unwrap(), depinfo); + + let depinfo = EncodedDepInfo { + files: vec![lib_rs, mod_rs], + env: vec![ + ("Gimli".into(), Some("Legolas".into())), + ("Beren".into(), Some("Lúthien".into())), + ], + }; + let data = depinfo.serialize().unwrap(); + assert_eq!(EncodedDepInfo::parse(&data).unwrap(), depinfo); + } + + #[test] + fn round_trip() { + gen_test(false); + } + + #[test] + fn round_trip_with_checksums() { + gen_test(true); + } + + #[test] + fn path_type_is_u8_max() { + #[rustfmt::skip] + let data = [ + 0x01, 0x00, 0x00, 0x00, 0xff, // magic marker + CURRENT_ENCODED_DEP_INFO_VERSION, // version + 0x01, 0x00, 0x00, 0x00, // # of files + 0x00, // path type + 0x04, 0x00, 0x00, 0x00, // len of path + 0x72, 0x75, 0x73, 0x74, // path bytes ("rust") + 0x00, // cksum exists? + 0x00, 0x00, 0x00, 0x00, // # of env vars + ]; + // The current cargo doesn't recognize the magic marker. + assert_eq!( + EncodedDepInfo::parse(&data).unwrap(), + EncodedDepInfo { + files: vec![(DepInfoPathType::PackageRootRelative, "rust".into(), None)], + env: Vec::new(), + } + ); + } + + #[test] + fn parse_v0_fingerprint_dep_info() { + #[rustfmt::skip] + let data = [ + 0x01, 0x00, 0x00, 0x00, // # of files + 0x00, // path type + 0x04, 0x00, 0x00, 0x00, // len of path + 0x72, 0x75, 0x73, 0x74, // path bytes: "rust" + 0x00, 0x00, 0x00, 0x00, // # of env vars + ]; + // Cargo can't recognize v0 after `-Zchecksum-freshess` added. + assert!(EncodedDepInfo::parse(&data).is_none()); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dirty_reason.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dirty_reason.rs new file mode 100644 index 000000000..6881f72a8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/dirty_reason.rs @@ -0,0 +1,330 @@ +use std::fmt; +use std::fmt::Debug; + +use super::*; +use crate::core::Shell; + +/// Tells a better story of why a build is considered "dirty" that leads +/// to a recompile. Usually constructed via [`Fingerprint::compare`]. +/// +/// [`Fingerprint::compare`]: super::Fingerprint::compare +#[derive(Clone, Debug)] +pub enum DirtyReason { + RustcChanged, + FeaturesChanged { + old: String, + new: String, + }, + DeclaredFeaturesChanged { + old: String, + new: String, + }, + TargetConfigurationChanged, + PathToSourceChanged, + ProfileConfigurationChanged, + RustflagsChanged { + old: Vec, + new: Vec, + }, + ConfigSettingsChanged, + CompileKindChanged, + LocalLengthsChanged, + PrecalculatedComponentsChanged { + old: String, + new: String, + }, + ChecksumUseChanged { + old: bool, + }, + DepInfoOutputChanged { + old: PathBuf, + new: PathBuf, + }, + RerunIfChangedOutputFileChanged { + old: PathBuf, + new: PathBuf, + }, + RerunIfChangedOutputPathsChanged { + old: Vec, + new: Vec, + }, + EnvVarsChanged { + old: String, + new: String, + }, + EnvVarChanged { + name: String, + old_value: Option, + new_value: Option, + }, + LocalFingerprintTypeChanged { + old: &'static str, + new: &'static str, + }, + NumberOfDependenciesChanged { + old: usize, + new: usize, + }, + UnitDependencyNameChanged { + old: InternedString, + new: InternedString, + }, + UnitDependencyInfoChanged { + old_name: InternedString, + old_fingerprint: u64, + + new_name: InternedString, + new_fingerprint: u64, + }, + FsStatusOutdated(FsStatus), + NothingObvious, + Forced, + /// First time to build something. + FreshBuild, +} + +trait ShellExt { + fn dirty_because(&mut self, unit: &Unit, s: impl fmt::Display) -> CargoResult<()>; +} + +impl ShellExt for Shell { + fn dirty_because(&mut self, unit: &Unit, s: impl fmt::Display) -> CargoResult<()> { + self.status("Dirty", format_args!("{}: {s}", &unit.pkg)) + } +} + +struct FileTimeDiff { + old_time: FileTime, + new_time: FileTime, +} + +impl fmt::Display for FileTimeDiff { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s_diff = self.new_time.seconds() - self.old_time.seconds(); + if s_diff >= 1 { + fmt::Display::fmt( + &humantime::Duration::from(std::time::Duration::from_secs(s_diff as u64)), + f, + ) + } else { + // format nanoseconds as it is, humantime would display ms, us and ns + let ns_diff = self.new_time.nanoseconds() - self.old_time.nanoseconds(); + write!(f, "{ns_diff}ns") + } + } +} + +#[derive(Copy, Clone)] +struct After { + old_time: FileTime, + new_time: FileTime, + what: &'static str, +} + +impl fmt::Display for After { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + old_time, + new_time, + what, + } = *self; + let diff = FileTimeDiff { old_time, new_time }; + + write!(f, "{new_time}, {diff} after {what} at {old_time}") + } +} + +impl DirtyReason { + /// Whether a build is dirty because it is a fresh build being kicked off. + pub fn is_fresh_build(&self) -> bool { + matches!(self, DirtyReason::FreshBuild) + } + + fn after(old_time: FileTime, new_time: FileTime, what: &'static str) -> After { + After { + old_time, + new_time, + what, + } + } + + pub fn present_to(&self, s: &mut Shell, unit: &Unit, root: &Path) -> CargoResult<()> { + match self { + DirtyReason::RustcChanged => s.dirty_because(unit, "the toolchain changed"), + DirtyReason::FeaturesChanged { .. } => { + s.dirty_because(unit, "the list of features changed") + } + DirtyReason::DeclaredFeaturesChanged { .. } => { + s.dirty_because(unit, "the list of declared features changed") + } + DirtyReason::TargetConfigurationChanged => { + s.dirty_because(unit, "the target configuration changed") + } + DirtyReason::PathToSourceChanged => { + s.dirty_because(unit, "the path to the source changed") + } + DirtyReason::ProfileConfigurationChanged => { + s.dirty_because(unit, "the profile configuration changed") + } + DirtyReason::RustflagsChanged { .. } => s.dirty_because(unit, "the rustflags changed"), + DirtyReason::ConfigSettingsChanged => { + s.dirty_because(unit, "the config settings changed") + } + DirtyReason::CompileKindChanged => { + s.dirty_because(unit, "the rustc compile kind changed") + } + DirtyReason::LocalLengthsChanged => { + s.dirty_because(unit, "the local lengths changed")?; + s.note( + "this could happen because of added/removed `cargo::rerun-if` instructions in the build script", + )?; + + Ok(()) + } + DirtyReason::PrecalculatedComponentsChanged { .. } => { + s.dirty_because(unit, "the precalculated components changed") + } + DirtyReason::ChecksumUseChanged { old } => { + if *old { + s.dirty_because( + unit, + "the prior compilation used checksum freshness and this one does not", + ) + } else { + s.dirty_because(unit, "checksum freshness requested, prior compilation did not use checksum freshness") + } + } + DirtyReason::DepInfoOutputChanged { .. } => { + s.dirty_because(unit, "the dependency info output changed") + } + DirtyReason::RerunIfChangedOutputFileChanged { .. } => { + s.dirty_because(unit, "rerun-if-changed output file path changed") + } + DirtyReason::RerunIfChangedOutputPathsChanged { .. } => { + s.dirty_because(unit, "the rerun-if-changed instructions changed") + } + DirtyReason::EnvVarsChanged { .. } => { + s.dirty_because(unit, "the environment variables changed") + } + DirtyReason::EnvVarChanged { name, .. } => { + s.dirty_because(unit, format_args!("the env variable {name} changed")) + } + DirtyReason::LocalFingerprintTypeChanged { .. } => { + s.dirty_because(unit, "the local fingerprint type changed") + } + DirtyReason::NumberOfDependenciesChanged { old, new } => s.dirty_because( + unit, + format_args!("number of dependencies changed ({old} => {new})",), + ), + DirtyReason::UnitDependencyNameChanged { old, new } => s.dirty_because( + unit, + format_args!("name of dependency changed ({old} => {new})"), + ), + DirtyReason::UnitDependencyInfoChanged { .. } => { + s.dirty_because(unit, "dependency info changed") + } + DirtyReason::FsStatusOutdated(status) => match status { + FsStatus::Stale => s.dirty_because(unit, "stale, unknown reason"), + FsStatus::StaleItem(item) => match item { + StaleItem::MissingFile(missing_file) => { + let file = missing_file.strip_prefix(root).unwrap_or(&missing_file); + s.dirty_because( + unit, + format_args!("the file `{}` is missing", file.display()), + ) + } + StaleItem::UnableToReadFile(file) => { + let file = file.strip_prefix(root).unwrap_or(&file); + s.dirty_because( + unit, + format_args!("the file `{}` could not be read", file.display()), + ) + } + StaleItem::FailedToReadMetadata(file) => { + let file = file.strip_prefix(root).unwrap_or(&file); + s.dirty_because( + unit, + format_args!("couldn't read metadata for file `{}`", file.display()), + ) + } + StaleItem::ChangedFile { + stale, + stale_mtime, + reference_mtime, + .. + } => { + let file = stale.strip_prefix(root).unwrap_or(&stale); + let after = Self::after(*reference_mtime, *stale_mtime, "last build"); + s.dirty_because( + unit, + format_args!("the file `{}` has changed ({after})", file.display()), + ) + } + StaleItem::ChangedChecksum { + source, + stored_checksum, + new_checksum, + } => { + let file = source.strip_prefix(root).unwrap_or(&source); + s.dirty_because( + unit, + format_args!( + "the file `{}` has changed (checksum didn't match, {stored_checksum} != {new_checksum})", + file.display(), + ), + ) + } + StaleItem::FileSizeChanged { + path, + old_size, + new_size, + } => { + let file = path.strip_prefix(root).unwrap_or(&path); + s.dirty_because( + unit, + format_args!( + "file size changed ({old_size} != {new_size}) for `{}`", + file.display() + ), + ) + } + StaleItem::MissingChecksum(path) => { + let file = path.strip_prefix(root).unwrap_or(&path); + s.dirty_because( + unit, + format_args!("the checksum for file `{}` is missing", file.display()), + ) + } + StaleItem::ChangedEnv { var, .. } => s.dirty_because( + unit, + format_args!("the environment variable {var} changed"), + ), + }, + FsStatus::StaleDependency { + name, + dep_mtime, + max_mtime, + .. + } => { + let after = Self::after(*max_mtime, *dep_mtime, "last build"); + s.dirty_because( + unit, + format_args!("the dependency {name} was rebuilt ({after})"), + ) + } + FsStatus::StaleDepFingerprint { name } => { + s.dirty_because(unit, format_args!("the dependency {name} was rebuilt")) + } + FsStatus::UpToDate { .. } => { + unreachable!() + } + }, + DirtyReason::NothingObvious => { + // See comment in fingerprint compare method. + s.dirty_because(unit, "the fingerprint comparison turned up nothing obvious") + } + DirtyReason::Forced => s.dirty_because(unit, "forced"), + DirtyReason::FreshBuild => s.dirty_because(unit, "fresh build"), + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/mod.rs new file mode 100644 index 000000000..b35a592ab --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/fingerprint/mod.rs @@ -0,0 +1,2065 @@ +//! Tracks changes to determine if something needs to be recompiled. +//! +//! This module implements change-tracking so that Cargo can know whether or +//! not something needs to be recompiled. A Cargo [`Unit`] can be either "dirty" +//! (needs to be recompiled) or "fresh" (it does not need to be recompiled). +//! +//! ## Mechanisms affecting freshness +//! +//! There are several mechanisms that influence a Unit's freshness: +//! +//! - The [`Fingerprint`] is a hash, saved to the filesystem in the +//! `.fingerprint` directory, that tracks information about the Unit. If the +//! fingerprint is missing (such as the first time the unit is being +//! compiled), then the unit is dirty. If any of the fingerprint fields +//! change (like the name of the source file), then the Unit is considered +//! dirty. +//! +//! The `Fingerprint` also tracks the fingerprints of all its dependencies, +//! so a change in a dependency will propagate the "dirty" status up. +//! +//! - Filesystem mtime tracking is also used to check if a unit is dirty. +//! See the section below on "Mtime comparison" for more details. There +//! are essentially two parts to mtime tracking: +//! +//! 1. The mtime of a Unit's output files is compared to the mtime of all +//! its dependencies' output file mtimes (see +//! [`check_filesystem`]). If any output is missing, or is +//! older than a dependency's output, then the unit is dirty. +//! 2. The mtime of a Unit's source files is compared to the mtime of its +//! dep-info file in the fingerprint directory (see [`find_stale_file`]). +//! The dep-info file is used as an anchor to know when the last build of +//! the unit was done. See the "dep-info files" section below for more +//! details. If any input files are missing, or are newer than the +//! dep-info, then the unit is dirty. +//! +//! - Alternatively if you're using the unstable feature `checksum-freshness` +//! mtimes are ignored entirely in favor of comparing first the file size, and +//! then the checksum with a known prior value emitted by rustc. Only nightly +//! rustc will emit the needed metadata at the time of writing. This is dependent +//! on the unstable feature `-Z checksum-hash-algorithm`. +//! +//! Note: Fingerprinting is not a perfect solution. Filesystem mtime tracking +//! is notoriously imprecise and problematic. Only a small part of the +//! environment is captured. This is a balance of performance, simplicity, and +//! completeness. Sandboxing, hashing file contents, tracking every file +//! access, environment variable, and network operation would ensure more +//! reliable and reproducible builds at the cost of being complex, slow, and +//! platform-dependent. +//! +//! ## Fingerprints and [`UnitHash`]s +//! +//! [`Metadata`] tracks several [`UnitHash`]s, including +//! [`Metadata::unit_id`], [`Metadata::c_metadata`], and [`Metadata::c_extra_filename`]. +//! See its documentation for more details. +//! +//! NOTE: Not all output files are isolated via filename hashes (like dylibs). +//! The fingerprint directory uses a hash, but sometimes units share the same +//! fingerprint directory (when they don't have Metadata) so care should be +//! taken to handle this! +//! +//! Fingerprints and [`UnitHash`]s are similar, and track some of the same things. +//! [`UnitHash`]s contains information that is required to keep Units separate. +//! The Fingerprint includes additional information that should cause a +//! recompile, but it is desired to reuse the same filenames. A comparison +//! of what is tracked: +//! +//! Value | Fingerprint | `Metadata::unit_id` | `Metadata::c_metadata` | `Metadata::c_extra_filename` +//! -------------------------------------------|-------------|---------------------|------------------------|---------- +//! rustc | ✓ | ✓ | ✓ | ✓ +//! [`Profile`] | ✓ | ✓ | ✓ | ✓ +//! `cargo rustc` extra args | ✓ | ✓[^7] | | ✓[^7] +//! [`CompileMode`] | ✓ | ✓ | ✓ | ✓ +//! Target Name | ✓ | ✓ | ✓ | ✓ +//! `TargetKind` (bin/lib/etc.) | ✓ | ✓ | ✓ | ✓ +//! Enabled Features | ✓ | ✓ | ✓ | ✓ +//! Declared Features | ✓ | | | +//! Immediate dependency’s hashes | ✓[^1] | ✓ | ✓ | ✓ +//! [`CompileKind`] (host/target) | ✓ | ✓ | ✓ | ✓ +//! `__CARGO_DEFAULT_LIB_METADATA`[^4] | | ✓ | ✓ | ✓ +//! `package_id` | | ✓ | ✓ | ✓ +//! Target src path relative to ws | ✓ | | | +//! Target flags (test/bench/for_host/edition) | ✓ | | | +//! -C incremental=… flag | ✓ | | | +//! mtime of sources | ✓[^3] | | | +//! RUSTFLAGS/RUSTDOCFLAGS | ✓ | ✓[^7] | | ✓[^7] +//! [`Lto`] flags | ✓ | ✓ | ✓ | ✓ +//! config settings[^5] | ✓ | | | +//! `is_std` | | ✓ | ✓ | ✓ +//! `[lints]` table[^6] | ✓ | | | +//! `[lints.rust.unexpected_cfgs.check-cfg]` | ✓ | | | +//! +//! [^1]: Build script and bin dependencies are not included. +//! +//! [^3]: See below for details on mtime tracking. +//! +//! [^4]: `__CARGO_DEFAULT_LIB_METADATA` is set by rustbuild to embed the +//! release channel (bootstrap/stable/beta/nightly) in libstd. +//! +//! [^5]: Config settings that are not otherwise captured anywhere else. +//! Currently, this is only `doc.extern-map`. +//! +//! [^6]: Via [`Manifest::lint_rustflags`][crate::core::Manifest::lint_rustflags] +//! +//! [^7]: extra-flags and RUSTFLAGS are conditionally excluded when `--remap-path-prefix` is +//! present to avoid breaking build reproducibility while we wait for trim-paths +//! +//! When deciding what should go in the Metadata vs the Fingerprint, consider +//! that some files (like dylibs) do not have a hash in their filename. Thus, +//! if a value changes, only the fingerprint will detect the change (consider, +//! for example, swapping between different features). Fields that are only in +//! Metadata generally aren't relevant to the fingerprint because they +//! fundamentally change the output (like target vs host changes the directory +//! where it is emitted). +//! +//! ## Fingerprint files +//! +//! Fingerprint information is stored in the +//! `target/{debug,release}/.fingerprint/` directory. Each Unit is stored in a +//! separate directory. Each Unit directory contains: +//! +//! - A file with a 16 hex-digit hash. This is the Fingerprint hash, used for +//! quick loading and comparison. +//! - A `.json` file that contains details about the Fingerprint. This is only +//! used to log details about *why* a fingerprint is considered dirty. +//! `CARGO_LOG=cargo::core::compiler::fingerprint=trace cargo build` can be +//! used to display this log information. +//! - A "dep-info" file which is a translation of rustc's `*.d` dep-info files +//! to a Cargo-specific format that tweaks file names and is optimized for +//! reading quickly. +//! - An `invoked.timestamp` file whose filesystem mtime is updated every time +//! the Unit is built. This is used for capturing the time when the build +//! starts, to detect if files are changed in the middle of the build. See +//! below for more details. +//! +//! Note that some units are a little different. A Unit for *running* a build +//! script or for `rustdoc` does not have a dep-info file (it's not +//! applicable). Build script `invoked.timestamp` files are in the build +//! output directory. +//! +//! ## Fingerprint calculation +//! +//! After the list of Units has been calculated, the Units are added to the +//! [`JobQueue`]. As each one is added, the fingerprint is calculated, and the +//! dirty/fresh status is recorded. A closure is used to update the fingerprint +//! on-disk when the Unit successfully finishes. The closure will recompute the +//! Fingerprint based on the updated information. If the Unit fails to compile, +//! the fingerprint is not updated. +//! +//! Fingerprints are cached in the [`BuildRunner`]. This makes computing +//! Fingerprints faster, but also is necessary for properly updating +//! dependency information. Since a Fingerprint includes the Fingerprints of +//! all dependencies, when it is updated, by using `Arc` clones, it +//! automatically picks up the updates to its dependencies. +//! +//! ### dep-info files +//! +//! Cargo has several kinds of "dep info" files: +//! +//! * dep-info files generated by `rustc`. +//! * Fingerprint dep-info files translated from the first one. +//! * dep-info for external build system integration. +//! * Unstable `-Zbinary-dep-depinfo`. +//! +//! #### `rustc` dep-info files +//! +//! Cargo passes the `--emit=dep-info` flag to `rustc` so that `rustc` will +//! generate a "dep info" file (with the `.d` extension). This is a +//! Makefile-like syntax that includes all of the source files used to build +//! the crate. This file is used by Cargo to know which files to check to see +//! if the crate will need to be rebuilt. Example: +//! +//! ```makefile +//! /path/to/target/debug/deps/cargo-b6219d178925203d: src/bin/main.rs src/bin/cargo/cli.rs # … etc. +//! ``` +//! +//! #### Fingerprint dep-info files +//! +//! After `rustc` exits successfully, Cargo will read the first kind of dep +//! info file and translate it into a binary format that is stored in the +//! fingerprint directory ([`translate_dep_info`]). +//! +//! These are used to quickly scan for any changed files. The mtime of the +//! fingerprint dep-info file itself is used as the reference for comparing the +//! source files to determine if any of the source files have been modified +//! (see [below](#mtime-comparison) for more detail). +//! +//! Note that Cargo parses the special `# env-var:...` comments in dep-info +//! files to learn about environment variables that the rustc compile depends on. +//! Cargo then later uses this to trigger a recompile if a referenced env var +//! changes (even if the source didn't change). +//! This also includes env vars generated from Cargo metadata like `CARGO_PKG_DESCRIPTION`. +//! (See [`crate::core::manifest::ManifestMetadata`] +//! +//! #### dep-info files for build system integration. +//! +//! There is also a third dep-info file. Cargo will extend the file created by +//! rustc with some additional information and saves this into the output +//! directory. This is intended for build system integration. See the +//! [`output_depinfo`] function for more detail. +//! +//! #### -Zbinary-dep-depinfo +//! +//! `rustc` has an experimental flag `-Zbinary-dep-depinfo`. This causes +//! `rustc` to include binary files (like rlibs) in the dep-info file. This is +//! primarily to support rustc development, so that Cargo can check the +//! implicit dependency to the standard library (which lives in the sysroot). +//! We want Cargo to recompile whenever the standard library rlib/dylibs +//! change, and this is a generic mechanism to make that work. +//! +//! ### Mtime comparison +//! +//! The use of modification timestamps is the most common way a unit will be +//! determined to be dirty or fresh between builds. There are many subtle +//! issues and edge cases with mtime comparisons. This gives a high-level +//! overview, but you'll need to read the code for the gritty details. Mtime +//! handling is different for different unit kinds. The different styles are +//! driven by the [`Fingerprint::local`] field, which is set based on the unit +//! kind. +//! +//! The status of whether or not the mtime is "stale" or "up-to-date" is +//! stored in [`Fingerprint::fs_status`]. +//! +//! All units will compare the mtime of its newest output file with the mtimes +//! of the outputs of all its dependencies. If any output file is missing, +//! then the unit is stale. If any dependency is newer, the unit is stale. +//! +//! #### Normal package mtime handling +//! +//! [`LocalFingerprint::CheckDepInfo`] is used for checking the mtime of +//! packages. It compares the mtime of the input files (the source files) to +//! the mtime of the dep-info file (which is written last after a build is +//! finished). If the dep-info is missing, the unit is stale (it has never +//! been built). The list of input files comes from the dep-info file. See the +//! section above for details on dep-info files. +//! +//! Also note that although registry and git packages use [`CheckDepInfo`], none +//! of their source files are included in the dep-info (see +//! [`translate_dep_info`]), so for those kinds no mtime checking is done +//! (unless `-Zbinary-dep-depinfo` is used). Repository and git packages are +//! static, so there is no need to check anything. +//! +//! When a build is complete, the mtime of the dep-info file in the +//! fingerprint directory is modified to rewind it to the time when the build +//! started. This is done by creating an `invoked.timestamp` file when the +//! build starts to capture the start time. The mtime is rewound to the start +//! to handle the case where the user modifies a source file while a build is +//! running. Cargo can't know whether or not the file was included in the +//! build, so it takes a conservative approach of assuming the file was *not* +//! included, and it should be rebuilt during the next build. +//! +//! #### Rustdoc mtime handling +//! +//! Rustdoc does not emit a dep-info file, so Cargo currently has a relatively +//! simple system for detecting rebuilds. [`LocalFingerprint::Precalculated`] is +//! used for rustdoc units. For registry packages, this is the package +//! version. For git packages, it is the git hash. For path packages, it is +//! the a string of the mtime of the newest file in the package. +//! +//! There are some known bugs with how this works, so it should be improved at +//! some point. +//! +//! #### Build script mtime handling +//! +//! Build script mtime handling runs in different modes. There is the "old +//! style" where the build script does not emit any `rerun-if` directives. In +//! this mode, Cargo will use [`LocalFingerprint::Precalculated`]. See the +//! "rustdoc" section above how it works. +//! +//! In the new-style, each `rerun-if` directive is translated to the +//! corresponding [`LocalFingerprint`] variant. The [`RerunIfChanged`] variant +//! compares the mtime of the given filenames against the mtime of the +//! "output" file. +//! +//! Similar to normal units, the build script "output" file mtime is rewound +//! to the time just before the build script is executed to handle mid-build +//! modifications. +//! +//! ## Considerations for inclusion in a fingerprint +//! +//! Over time we've realized a few items which historically were included in +//! fingerprint hashings should not actually be included. Examples are: +//! +//! * Modification time values. We strive to never include a modification time +//! inside a `Fingerprint` to get hashed into an actual value. While +//! theoretically fine to do, in practice this causes issues with common +//! applications like Docker. Docker, after a layer is built, will zero out +//! the nanosecond part of all filesystem modification times. This means that +//! the actual modification time is different for all build artifacts, which +//! if we tracked the actual values of modification times would cause +//! unnecessary recompiles. To fix this we instead only track paths which are +//! relevant. These paths are checked dynamically to see if they're up to +//! date, and the modification time doesn't make its way into the fingerprint +//! hash. +//! +//! * Absolute path names. We strive to maintain a property where if you rename +//! a project directory Cargo will continue to preserve all build artifacts +//! and reuse the cache. This means that we can't ever hash an absolute path +//! name. Instead we always hash relative path names and the "root" is passed +//! in at runtime dynamically. Some of this is best effort, but the general +//! idea is that we assume all accesses within a crate stay within that +//! crate. +//! +//! These are pretty tricky to test for unfortunately, but we should have a good +//! test suite nowadays and lord knows Cargo gets enough testing in the wild! +//! +//! ## Build scripts +//! +//! The *running* of a build script ([`CompileMode::RunCustomBuild`]) is treated +//! significantly different than all other Unit kinds. It has its own function +//! for calculating the Fingerprint ([`calculate_run_custom_build`]) and has some +//! unique considerations. It does not track the same information as a normal +//! Unit. The information tracked depends on the `rerun-if-changed` and +//! `rerun-if-env-changed` statements produced by the build script. If the +//! script does not emit either of these statements, the Fingerprint runs in +//! "old style" mode where an mtime change of *any* file in the package will +//! cause the build script to be re-run. Otherwise, the fingerprint *only* +//! tracks the individual "rerun-if" items listed by the build script. +//! +//! The "rerun-if" statements from a *previous* build are stored in the build +//! output directory in a file called `output`. Cargo parses this file when +//! the Unit for that build script is prepared for the [`JobQueue`]. The +//! Fingerprint code can then use that information to compute the Fingerprint +//! and compare against the old fingerprint hash. +//! +//! Care must be taken with build script Fingerprints because the +//! [`Fingerprint::local`] value may be changed after the build script runs +//! (such as if the build script adds or removes "rerun-if" items). +//! +//! Another complication is if a build script is overridden. In that case, the +//! fingerprint is the hash of the output of the override. +//! +//! ## Special considerations +//! +//! Registry dependencies do not track the mtime of files. This is because +//! registry dependencies are not expected to change (if a new version is +//! used, the Package ID will change, causing a rebuild). Cargo currently +//! partially works with Docker caching. When a Docker image is built, it has +//! normal mtime information. However, when a step is cached, the nanosecond +//! portions of all files is zeroed out. Currently this works, but care must +//! be taken for situations like these. +//! +//! HFS on macOS only supports 1 second timestamps. This causes a significant +//! number of problems, particularly with Cargo's testsuite which does rapid +//! builds in succession. Other filesystems have various degrees of +//! resolution. +//! +//! Various weird filesystems (such as network filesystems) also can cause +//! complications. Network filesystems may track the time on the server +//! (except when the time is set manually such as with +//! `filetime::set_file_times`). Not all filesystems support modifying the +//! mtime. +//! +//! See the [`A-rebuild-detection`] label on the issue tracker for more. +//! +//! [`check_filesystem`]: Fingerprint::check_filesystem +//! [`Metadata`]: crate::core::compiler::Metadata +//! [`Metadata::unit_id`]: crate::core::compiler::Metadata::unit_id +//! [`Metadata::c_metadata`]: crate::core::compiler::Metadata::c_metadata +//! [`Metadata::c_extra_filename`]: crate::core::compiler::Metadata::c_extra_filename +//! [`UnitHash`]: crate::core::compiler::UnitHash +//! [`Profile`]: crate::core::profiles::Profile +//! [`CompileMode`]: crate::core::compiler::CompileMode +//! [`Lto`]: crate::core::compiler::Lto +//! [`CompileKind`]: crate::core::compiler::CompileKind +//! [`JobQueue`]: super::job_queue::JobQueue +//! [`output_depinfo`]: super::output_depinfo() +//! [`CheckDepInfo`]: LocalFingerprint::CheckDepInfo +//! [`RerunIfChanged`]: LocalFingerprint::RerunIfChanged +//! [`CompileMode::RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild +//! [`A-rebuild-detection`]: https://github.com/rust-lang/cargo/issues?q=is%3Aissue+is%3Aopen+label%3AA-rebuild-detection + +mod dep_info; +mod dirty_reason; + +use std::collections::hash_map::{Entry, HashMap}; +use std::env; +use std::ffi::OsString; +use std::fs; +use std::fs::File; +use std::hash::{self, Hash, Hasher}; +use std::io::{self}; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; +use std::time::SystemTime; + +use anyhow::format_err; +use anyhow::Context as _; +use cargo_util::paths; +use filetime::FileTime; +use serde::de; +use serde::ser; +use serde::{Deserialize, Serialize}; +use tracing::{debug, info}; + +use crate::core::compiler::unit_graph::UnitDep; +use crate::core::Package; +use crate::util; +use crate::util::errors::CargoResult; +use crate::util::interning::InternedString; +use crate::util::{internal, path_args, StableHasher}; +use crate::{GlobalContext, CARGO_ENV}; + +use super::custom_build::BuildDeps; +use super::{BuildContext, BuildRunner, FileFlavor, Job, Unit, Work}; + +pub use self::dep_info::parse_dep_info; +pub use self::dep_info::parse_rustc_dep_info; +pub use self::dep_info::translate_dep_info; +pub use self::dep_info::Checksum; +pub use self::dirty_reason::DirtyReason; + +/// Determines if a [`Unit`] is up-to-date, and if not prepares necessary work to +/// update the persisted fingerprint. +/// +/// This function will inspect `Unit`, calculate a fingerprint for it, and then +/// return an appropriate [`Job`] to run. The returned `Job` will be a noop if +/// `unit` is considered "fresh", or if it was previously built and cached. +/// Otherwise the `Job` returned will write out the true fingerprint to the +/// filesystem, to be executed after the unit's work has completed. +/// +/// The `force` flag is a way to force the `Job` to be "dirty", or always +/// update the fingerprint. **Beware using this flag** because it does not +/// transitively propagate throughout the dependency graph, it only forces this +/// one unit which is very unlikely to be what you want unless you're +/// exclusively talking about top-level units. +#[tracing::instrument( + skip(build_runner, unit), + fields(package_id = %unit.pkg.package_id(), target = unit.target.name()) +)] +pub fn prepare_target( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, + force: bool, +) -> CargoResult { + let bcx = build_runner.bcx; + let loc = build_runner.files().fingerprint_file_path(unit, ""); + + debug!("fingerprint at: {}", loc.display()); + + // Figure out if this unit is up to date. After calculating the fingerprint + // compare it to an old version, if any, and attempt to print diagnostic + // information about failed comparisons to aid in debugging. + let fingerprint = calculate(build_runner, unit)?; + let mtime_on_use = build_runner.bcx.gctx.cli_unstable().mtime_on_use; + let dirty_reason = compare_old_fingerprint(unit, &loc, &*fingerprint, mtime_on_use, force); + + let Some(dirty_reason) = dirty_reason else { + return Ok(Job::new_fresh()); + }; + + // We're going to rebuild, so ensure the source of the crate passes all + // verification checks before we build it. + // + // The `Source::verify` method is intended to allow sources to execute + // pre-build checks to ensure that the relevant source code is all + // up-to-date and as expected. This is currently used primarily for + // directory sources which will use this hook to perform an integrity check + // on all files in the source to ensure they haven't changed. If they have + // changed then an error is issued. + let source_id = unit.pkg.package_id().source_id(); + let sources = bcx.packages.sources(); + let source = sources + .get(source_id) + .ok_or_else(|| internal("missing package source"))?; + source.verify(unit.pkg.package_id())?; + + // Clear out the old fingerprint file if it exists. This protects when + // compilation is interrupted leaving a corrupt file. For example, a + // project with a lib.rs and integration test (two units): + // + // 1. Build the library and integration test. + // 2. Make a change to lib.rs (NOT the integration test). + // 3. Build the integration test, hit Ctrl-C while linking. With gcc, this + // will leave behind an incomplete executable (zero size, or partially + // written). NOTE: The library builds successfully, it is the linking + // of the integration test that we are interrupting. + // 4. Build the integration test again. + // + // Without the following line, then step 3 will leave a valid fingerprint + // on the disk. Then step 4 will think the integration test is "fresh" + // because: + // + // - There is a valid fingerprint hash on disk (written in step 1). + // - The mtime of the output file (the corrupt integration executable + // written in step 3) is newer than all of its dependencies. + // - The mtime of the integration test fingerprint dep-info file (written + // in step 1) is newer than the integration test's source files, because + // we haven't modified any of its source files. + // + // But the executable is corrupt and needs to be rebuilt. Clearing the + // fingerprint at step 3 ensures that Cargo never mistakes a partially + // written output as up-to-date. + if loc.exists() { + // Truncate instead of delete so that compare_old_fingerprint will + // still log the reason for the fingerprint failure instead of just + // reporting "failed to read fingerprint" during the next build if + // this build fails. + paths::write(&loc, b"")?; + } + + let write_fingerprint = if unit.mode.is_run_custom_build() { + // For build scripts the `local` field of the fingerprint may change + // while we're executing it. For example it could be in the legacy + // "consider everything a dependency mode" and then we switch to "deps + // are explicitly specified" mode. + // + // To handle this movement we need to regenerate the `local` field of a + // build script's fingerprint after it's executed. We do this by + // using the `build_script_local_fingerprints` function which returns a + // thunk we can invoke on a foreign thread to calculate this. + let build_script_outputs = Arc::clone(&build_runner.build_script_outputs); + let metadata = build_runner.get_run_build_script_metadata(unit); + let (gen_local, _overridden) = build_script_local_fingerprints(build_runner, unit)?; + let output_path = build_runner.build_explicit_deps[unit] + .build_script_output + .clone(); + Work::new(move |_| { + let outputs = build_script_outputs.lock().unwrap(); + let output = outputs + .get(metadata) + .expect("output must exist after running"); + let deps = BuildDeps::new(&output_path, Some(output)); + + // FIXME: it's basically buggy that we pass `None` to `call_box` + // here. See documentation on `build_script_local_fingerprints` + // below for more information. Despite this just try to proceed and + // hobble along if it happens to return `Some`. + if let Some(new_local) = (gen_local)(&deps, None)? { + *fingerprint.local.lock().unwrap() = new_local; + } + + write_fingerprint(&loc, &fingerprint) + }) + } else { + Work::new(move |_| write_fingerprint(&loc, &fingerprint)) + }; + + Ok(Job::new_dirty(write_fingerprint, dirty_reason)) +} + +/// Dependency edge information for fingerprints. This is generated for each +/// dependency and is stored in a [`Fingerprint`]. +#[derive(Clone)] +struct DepFingerprint { + /// The hash of the package id that this dependency points to + pkg_id: u64, + /// The crate name we're using for this dependency, which if we change we'll + /// need to recompile! + name: InternedString, + /// Whether or not this dependency is flagged as a public dependency or not. + public: bool, + /// Whether or not this dependency is an rmeta dependency or a "full" + /// dependency. In the case of an rmeta dependency our dependency edge only + /// actually requires the rmeta from what we depend on, so when checking + /// mtime information all files other than the rmeta can be ignored. + only_requires_rmeta: bool, + /// The dependency's fingerprint we recursively point to, containing all the + /// other hash information we'd otherwise need. + fingerprint: Arc, +} + +/// A fingerprint can be considered to be a "short string" representing the +/// state of a world for a package. +/// +/// If a fingerprint ever changes, then the package itself needs to be +/// recompiled. Inputs to the fingerprint include source code modifications, +/// compiler flags, compiler version, etc. This structure is not simply a +/// `String` due to the fact that some fingerprints cannot be calculated lazily. +/// +/// Path sources, for example, use the mtime of the corresponding dep-info file +/// as a fingerprint (all source files must be modified *before* this mtime). +/// This dep-info file is not generated, however, until after the crate is +/// compiled. As a result, this structure can be thought of as a fingerprint +/// to-be. The actual value can be calculated via [`hash_u64()`], but the operation +/// may fail as some files may not have been generated. +/// +/// Note that dependencies are taken into account for fingerprints because rustc +/// requires that whenever an upstream crate is recompiled that all downstream +/// dependents are also recompiled. This is typically tracked through +/// [`DependencyQueue`], but it also needs to be retained here because Cargo can +/// be interrupted while executing, losing the state of the [`DependencyQueue`] +/// graph. +/// +/// [`hash_u64()`]: crate::core::compiler::fingerprint::Fingerprint::hash_u64 +/// [`DependencyQueue`]: crate::util::DependencyQueue +#[derive(Serialize, Deserialize)] +pub struct Fingerprint { + /// Hash of the version of `rustc` used. + rustc: u64, + /// Sorted list of cfg features enabled. + features: String, + /// Sorted list of all the declared cfg features. + declared_features: String, + /// Hash of the `Target` struct, including the target name, + /// package-relative source path, edition, etc. + target: u64, + /// Hash of the [`Profile`], [`CompileMode`], and any extra flags passed via + /// `cargo rustc` or `cargo rustdoc`. + /// + /// [`Profile`]: crate::core::profiles::Profile + /// [`CompileMode`]: crate::core::compiler::CompileMode + profile: u64, + /// Hash of the path to the base source file. This is relative to the + /// workspace root for path members, or absolute for other sources. + path: u64, + /// Fingerprints of dependencies. + deps: Vec, + /// Information about the inputs that affect this Unit (such as source + /// file mtimes or build script environment variables). + local: Mutex>, + /// Cached hash of the [`Fingerprint`] struct. Used to improve performance + /// for hashing. + #[serde(skip)] + memoized_hash: Mutex>, + /// RUSTFLAGS/RUSTDOCFLAGS environment variable value (or config value). + rustflags: Vec, + /// Hash of various config settings that change how things are compiled. + config: u64, + /// The rustc target. This is only relevant for `.json` files, otherwise + /// the metadata hash segregates the units. + compile_kind: u64, + /// Description of whether the filesystem status for this unit is up to date + /// or should be considered stale. + #[serde(skip)] + fs_status: FsStatus, + /// Files, relative to `target_root`, that are produced by the step that + /// this `Fingerprint` represents. This is used to detect when the whole + /// fingerprint is out of date if this is missing, or if previous + /// fingerprints output files are regenerated and look newer than this one. + #[serde(skip)] + outputs: Vec, +} + +/// Indication of the status on the filesystem for a particular unit. +#[derive(Clone, Default, Debug)] +pub enum FsStatus { + /// This unit is to be considered stale, even if hash information all + /// matches. + #[default] + Stale, + + /// File system inputs have changed (or are missing), or there were + /// changes to the environment variables that affect this unit. See + /// the variants of [`StaleItem`] for more information. + StaleItem(StaleItem), + + /// A dependency was stale. + StaleDependency { + name: InternedString, + dep_mtime: FileTime, + max_mtime: FileTime, + }, + + /// A dependency was stale. + StaleDepFingerprint { name: InternedString }, + + /// This unit is up-to-date. All outputs and their corresponding mtime are + /// listed in the payload here for other dependencies to compare against. + UpToDate { mtimes: HashMap }, +} + +impl FsStatus { + fn up_to_date(&self) -> bool { + match self { + FsStatus::UpToDate { .. } => true, + FsStatus::Stale + | FsStatus::StaleItem(_) + | FsStatus::StaleDependency { .. } + | FsStatus::StaleDepFingerprint { .. } => false, + } + } +} + +impl Serialize for DepFingerprint { + fn serialize(&self, ser: S) -> Result + where + S: ser::Serializer, + { + ( + &self.pkg_id, + &self.name, + &self.public, + &self.fingerprint.hash_u64(), + ) + .serialize(ser) + } +} + +impl<'de> Deserialize<'de> for DepFingerprint { + fn deserialize(d: D) -> Result + where + D: de::Deserializer<'de>, + { + let (pkg_id, name, public, hash) = <(u64, String, bool, u64)>::deserialize(d)?; + Ok(DepFingerprint { + pkg_id, + name: InternedString::new(&name), + public, + fingerprint: Arc::new(Fingerprint { + memoized_hash: Mutex::new(Some(hash)), + ..Fingerprint::new() + }), + // This field is never read since it's only used in + // `check_filesystem` which isn't used by fingerprints loaded from + // disk. + only_requires_rmeta: false, + }) + } +} + +/// A `LocalFingerprint` represents something that we use to detect direct +/// changes to a `Fingerprint`. +/// +/// This is where we track file information, env vars, etc. This +/// `LocalFingerprint` struct is hashed and if the hash changes will force a +/// recompile of any fingerprint it's included into. Note that the "local" +/// terminology comes from the fact that it only has to do with one crate, and +/// `Fingerprint` tracks the transitive propagation of fingerprint changes. +/// +/// Note that because this is hashed its contents are carefully managed. Like +/// mentioned in the above module docs, we don't want to hash absolute paths or +/// mtime information. +/// +/// Also note that a `LocalFingerprint` is used in `check_filesystem` to detect +/// when the filesystem contains stale information (based on mtime currently). +/// The paths here don't change much between compilations but they're used as +/// inputs when we probe the filesystem looking at information. +#[derive(Debug, Serialize, Deserialize, Hash)] +enum LocalFingerprint { + /// This is a precalculated fingerprint which has an opaque string we just + /// hash as usual. This variant is primarily used for rustdoc where we + /// don't have a dep-info file to compare against. + /// + /// This is also used for build scripts with no `rerun-if-*` statements, but + /// that's overall a mistake and causes bugs in Cargo. We shouldn't use this + /// for build scripts. + Precalculated(String), + + /// This is used for crate compilations. The `dep_info` file is a relative + /// path anchored at `target_root(...)` to the dep-info file that Cargo + /// generates (which is a custom serialization after parsing rustc's own + /// `dep-info` output). + /// + /// The `dep_info` file, when present, also lists a number of other files + /// for us to look at. If any of those files are newer than this file then + /// we need to recompile. + /// + /// If the `checksum` bool is true then the `dep_info` file is expected to + /// contain file checksums instead of file mtimes. + CheckDepInfo { dep_info: PathBuf, checksum: bool }, + + /// This represents a nonempty set of `rerun-if-changed` annotations printed + /// out by a build script. The `output` file is a relative file anchored at + /// `target_root(...)` which is the actual output of the build script. That + /// output has already been parsed and the paths printed out via + /// `rerun-if-changed` are listed in `paths`. The `paths` field is relative + /// to `pkg.root()` + /// + /// This is considered up-to-date if all of the `paths` are older than + /// `output`, otherwise we need to recompile. + RerunIfChanged { + output: PathBuf, + paths: Vec, + }, + + /// This represents a single `rerun-if-env-changed` annotation printed by a + /// build script. The exact env var and value are hashed here. There's no + /// filesystem dependence here, and if the values are changed the hash will + /// change forcing a recompile. + RerunIfEnvChanged { var: String, val: Option }, +} + +/// See [`FsStatus::StaleItem`]. +#[derive(Clone, Debug)] +pub enum StaleItem { + MissingFile(PathBuf), + UnableToReadFile(PathBuf), + FailedToReadMetadata(PathBuf), + FileSizeChanged { + path: PathBuf, + old_size: u64, + new_size: u64, + }, + ChangedFile { + reference: PathBuf, + reference_mtime: FileTime, + stale: PathBuf, + stale_mtime: FileTime, + }, + ChangedChecksum { + source: PathBuf, + stored_checksum: Checksum, + new_checksum: Checksum, + }, + MissingChecksum(PathBuf), + ChangedEnv { + var: String, + previous: Option, + current: Option, + }, +} + +impl LocalFingerprint { + /// Read the environment variable of the given env `key`, and creates a new + /// [`LocalFingerprint::RerunIfEnvChanged`] for it. The `env_config` is used firstly + /// to check if the env var is set in the config system as some envs need to be overridden. + /// If not, it will fallback to `std::env::var`. + /// + // TODO: `std::env::var` is allowed at this moment. Should figure out + // if it makes sense if permitting to read env from the env snapshot. + #[allow(clippy::disallowed_methods)] + fn from_env>( + key: K, + env_config: &Arc>, + ) -> LocalFingerprint { + let key = key.as_ref(); + let var = key.to_owned(); + let val = if let Some(val) = env_config.get(key) { + val.to_str().map(ToOwned::to_owned) + } else { + env::var(key).ok() + }; + LocalFingerprint::RerunIfEnvChanged { var, val } + } + + /// Checks dynamically at runtime if this `LocalFingerprint` has a stale + /// item inside of it. + /// + /// The main purpose of this function is to handle two different ways + /// fingerprints can be invalidated: + /// + /// * One is a dependency listed in rustc's dep-info files is invalid. Note + /// that these could either be env vars or files. We check both here. + /// + /// * Another is the `rerun-if-changed` directive from build scripts. This + /// is where we'll find whether files have actually changed + fn find_stale_item( + &self, + mtime_cache: &mut HashMap, + checksum_cache: &mut HashMap, + pkg: &Package, + target_root: &Path, + cargo_exe: &Path, + gctx: &GlobalContext, + ) -> CargoResult> { + let pkg_root = pkg.root(); + match self { + // We need to parse `dep_info`, learn about the crate's dependencies. + // + // For each env var we see if our current process's env var still + // matches, and for each file we see if any of them are newer than + // the `dep_info` file itself whose mtime represents the start of + // rustc. + LocalFingerprint::CheckDepInfo { dep_info, checksum } => { + let dep_info = target_root.join(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() { + if let Some(value) = pkg.manifest().metadata().env_var(key.as_str()) { + if Some(value.as_ref()) == previous.as_deref() { + continue; + } + } + + let current = if key == CARGO_ENV { + Some(cargo_exe.to_str().ok_or_else(|| { + format_err!( + "cargo exe path {} must be valid UTF-8", + cargo_exe.display() + ) + })?) + } else { + if let Some(value) = gctx.env_config()?.get(key) { + value.to_str() + } else { + gctx.get_env(key).ok() + } + }; + if current == previous.as_deref() { + continue; + } + return Ok(Some(StaleItem::ChangedEnv { + var: key.clone(), + previous: previous.clone(), + current: current.map(Into::into), + })); + } + if *checksum { + Ok(find_stale_file( + mtime_cache, + checksum_cache, + &dep_info, + info.files.iter().map(|(file, checksum)| (file, *checksum)), + *checksum, + )) + } else { + Ok(find_stale_file( + mtime_cache, + checksum_cache, + &dep_info, + info.files.into_keys().map(|p| (p, None)), + *checksum, + )) + } + } + + // We need to verify that no paths listed in `paths` are newer than + // the `output` path itself, or the last time the build script ran. + LocalFingerprint::RerunIfChanged { output, paths } => Ok(find_stale_file( + mtime_cache, + checksum_cache, + &target_root.join(output), + paths.iter().map(|p| (pkg_root.join(p), None)), + false, + )), + + // These have no dependencies on the filesystem, and their values + // are included natively in the `Fingerprint` hash so nothing + // tocheck for here. + LocalFingerprint::RerunIfEnvChanged { .. } => Ok(None), + LocalFingerprint::Precalculated(..) => Ok(None), + } + } + + fn kind(&self) -> &'static str { + match self { + LocalFingerprint::Precalculated(..) => "precalculated", + LocalFingerprint::CheckDepInfo { .. } => "dep-info", + LocalFingerprint::RerunIfChanged { .. } => "rerun-if-changed", + LocalFingerprint::RerunIfEnvChanged { .. } => "rerun-if-env-changed", + } + } +} + +impl Fingerprint { + fn new() -> Fingerprint { + Fingerprint { + rustc: 0, + target: 0, + profile: 0, + path: 0, + features: String::new(), + declared_features: String::new(), + deps: Vec::new(), + local: Mutex::new(Vec::new()), + memoized_hash: Mutex::new(None), + rustflags: Vec::new(), + config: 0, + compile_kind: 0, + fs_status: FsStatus::Stale, + outputs: Vec::new(), + } + } + + /// For performance reasons fingerprints will memoize their own hash, but + /// there's also internal mutability with its `local` field which can + /// change, for example with build scripts, during a build. + /// + /// This method can be used to bust all memoized hashes just before a build + /// to ensure that after a build completes everything is up-to-date. + pub fn clear_memoized(&self) { + *self.memoized_hash.lock().unwrap() = None; + } + + fn hash_u64(&self) -> u64 { + if let Some(s) = *self.memoized_hash.lock().unwrap() { + return s; + } + let ret = util::hash_u64(self); + *self.memoized_hash.lock().unwrap() = Some(ret); + ret + } + + /// Compares this fingerprint with an old version which was previously + /// serialized to filesystem. + /// + /// The purpose of this is exclusively to produce a diagnostic message + /// [`DirtyReason`], indicating why we're recompiling something. + fn compare(&self, old: &Fingerprint) -> DirtyReason { + if self.rustc != old.rustc { + return DirtyReason::RustcChanged; + } + if self.features != old.features { + return DirtyReason::FeaturesChanged { + old: old.features.clone(), + new: self.features.clone(), + }; + } + if self.declared_features != old.declared_features { + return DirtyReason::DeclaredFeaturesChanged { + old: old.declared_features.clone(), + new: self.declared_features.clone(), + }; + } + if self.target != old.target { + return DirtyReason::TargetConfigurationChanged; + } + if self.path != old.path { + return DirtyReason::PathToSourceChanged; + } + if self.profile != old.profile { + return DirtyReason::ProfileConfigurationChanged; + } + if self.rustflags != old.rustflags { + return DirtyReason::RustflagsChanged { + old: old.rustflags.clone(), + new: self.rustflags.clone(), + }; + } + if self.config != old.config { + return DirtyReason::ConfigSettingsChanged; + } + if self.compile_kind != old.compile_kind { + return DirtyReason::CompileKindChanged; + } + let my_local = self.local.lock().unwrap(); + let old_local = old.local.lock().unwrap(); + if my_local.len() != old_local.len() { + return DirtyReason::LocalLengthsChanged; + } + for (new, old) in my_local.iter().zip(old_local.iter()) { + match (new, old) { + (LocalFingerprint::Precalculated(a), LocalFingerprint::Precalculated(b)) => { + if a != b { + return DirtyReason::PrecalculatedComponentsChanged { + old: b.to_string(), + new: a.to_string(), + }; + } + } + ( + LocalFingerprint::CheckDepInfo { + dep_info: adep, + checksum: checksum_a, + }, + LocalFingerprint::CheckDepInfo { + dep_info: bdep, + checksum: checksum_b, + }, + ) => { + if adep != bdep { + return DirtyReason::DepInfoOutputChanged { + old: bdep.clone(), + new: adep.clone(), + }; + } + if checksum_a != checksum_b { + return DirtyReason::ChecksumUseChanged { old: *checksum_b }; + } + } + ( + LocalFingerprint::RerunIfChanged { + output: aout, + paths: apaths, + }, + LocalFingerprint::RerunIfChanged { + output: bout, + paths: bpaths, + }, + ) => { + if aout != bout { + return DirtyReason::RerunIfChangedOutputFileChanged { + old: bout.clone(), + new: aout.clone(), + }; + } + if apaths != bpaths { + return DirtyReason::RerunIfChangedOutputPathsChanged { + old: bpaths.clone(), + new: apaths.clone(), + }; + } + } + ( + LocalFingerprint::RerunIfEnvChanged { + var: akey, + val: avalue, + }, + LocalFingerprint::RerunIfEnvChanged { + var: bkey, + val: bvalue, + }, + ) => { + if *akey != *bkey { + return DirtyReason::EnvVarsChanged { + old: bkey.clone(), + new: akey.clone(), + }; + } + if *avalue != *bvalue { + return DirtyReason::EnvVarChanged { + name: akey.clone(), + old_value: bvalue.clone(), + new_value: avalue.clone(), + }; + } + } + (a, b) => { + return DirtyReason::LocalFingerprintTypeChanged { + old: b.kind(), + new: a.kind(), + } + } + } + } + + if self.deps.len() != old.deps.len() { + return DirtyReason::NumberOfDependenciesChanged { + old: old.deps.len(), + new: self.deps.len(), + }; + } + for (a, b) in self.deps.iter().zip(old.deps.iter()) { + if a.name != b.name { + return DirtyReason::UnitDependencyNameChanged { + old: b.name, + new: a.name, + }; + } + + if a.fingerprint.hash_u64() != b.fingerprint.hash_u64() { + return DirtyReason::UnitDependencyInfoChanged { + new_name: a.name, + new_fingerprint: a.fingerprint.hash_u64(), + old_name: b.name, + old_fingerprint: b.fingerprint.hash_u64(), + }; + } + } + + if !self.fs_status.up_to_date() { + return DirtyReason::FsStatusOutdated(self.fs_status.clone()); + } + + // This typically means some filesystem modifications happened or + // something transitive was odd. In general we should strive to provide + // a better error message than this, so if you see this message a lot it + // likely means this method needs to be updated! + DirtyReason::NothingObvious + } + + /// Dynamically inspect the local filesystem to update the `fs_status` field + /// of this `Fingerprint`. + /// + /// This function is used just after a `Fingerprint` is constructed to check + /// the local state of the filesystem and propagate any dirtiness from + /// dependencies up to this unit as well. This function assumes that the + /// unit starts out as [`FsStatus::Stale`] and then it will optionally switch + /// it to `UpToDate` if it can. + fn check_filesystem( + &mut self, + mtime_cache: &mut HashMap, + checksum_cache: &mut HashMap, + pkg: &Package, + target_root: &Path, + cargo_exe: &Path, + gctx: &GlobalContext, + ) -> CargoResult<()> { + assert!(!self.fs_status.up_to_date()); + + let pkg_root = pkg.root(); + let mut mtimes = HashMap::new(); + + // Get the `mtime` of all outputs. Optionally update their mtime + // afterwards based on the `mtime_on_use` flag. Afterwards we want the + // minimum mtime as it's the one we'll be comparing to inputs and + // dependencies. + for output in self.outputs.iter() { + let mtime = match paths::mtime(output) { + Ok(mtime) => mtime, + + // This path failed to report its `mtime`. It probably doesn't + // exists, so leave ourselves as stale and bail out. + Err(e) => { + debug!("failed to get mtime of {:?}: {}", output, e); + return Ok(()); + } + }; + assert!(mtimes.insert(output.clone(), mtime).is_none()); + } + + let opt_max = mtimes.iter().max_by_key(|kv| kv.1); + 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. + self.fs_status = FsStatus::UpToDate { mtimes }; + return Ok(()); + }; + debug!( + "max output mtime for {:?} is {:?} {}", + pkg_root, max_path, max_mtime + ); + + for dep in self.deps.iter() { + let dep_mtimes = match &dep.fingerprint.fs_status { + FsStatus::UpToDate { mtimes } => mtimes, + // If our dependency is stale, so are we, so bail out. + FsStatus::Stale + | FsStatus::StaleItem(_) + | FsStatus::StaleDependency { .. } + | FsStatus::StaleDepFingerprint { .. } => { + self.fs_status = FsStatus::StaleDepFingerprint { name: dep.name }; + return Ok(()); + } + }; + + // If our dependency edge only requires the rmeta file to be present + // then we only need to look at that one output file, otherwise we + // need to consider all output files to see if we're out of date. + let (dep_path, dep_mtime) = if dep.only_requires_rmeta { + dep_mtimes + .iter() + .find(|(path, _mtime)| { + path.extension().and_then(|s| s.to_str()) == Some("rmeta") + }) + .expect("failed to find rmeta") + } else { + match dep_mtimes.iter().max_by_key(|kv| kv.1) { + Some(dep_mtime) => dep_mtime, + // If our dependencies is up to date and has no filesystem + // interactions, then we can move on to the next dependency. + None => continue, + } + }; + debug!( + "max dep mtime for {:?} is {:?} {}", + pkg_root, dep_path, dep_mtime + ); + + // If the dependency is newer than our own output then it was + // recompiled previously. We transitively become stale ourselves in + // that case, so bail out. + // + // Note that this comparison should probably be `>=`, not `>`, but + // for a discussion of why it's `>` see the discussion about #5918 + // below in `find_stale`. + if dep_mtime > max_mtime { + info!( + "dependency on `{}` is newer than we are {} > {} {:?}", + dep.name, dep_mtime, max_mtime, pkg_root + ); + + self.fs_status = FsStatus::StaleDependency { + name: dep.name, + dep_mtime: *dep_mtime, + max_mtime: *max_mtime, + }; + + return Ok(()); + } + } + + // If we reached this far then all dependencies are up to date. Check + // all our `LocalFingerprint` information to see if we have any stale + // files for this package itself. If we do find something log a helpful + // message and bail out so we stay stale. + for local in self.local.get_mut().unwrap().iter() { + if let Some(item) = local.find_stale_item( + mtime_cache, + checksum_cache, + pkg, + target_root, + cargo_exe, + gctx, + )? { + item.log(); + self.fs_status = FsStatus::StaleItem(item); + return Ok(()); + } + } + + // Everything was up to date! Record such. + self.fs_status = FsStatus::UpToDate { mtimes }; + debug!("filesystem up-to-date {:?}", pkg_root); + + Ok(()) + } +} + +impl hash::Hash for Fingerprint { + fn hash(&self, h: &mut H) { + let Fingerprint { + rustc, + ref features, + ref declared_features, + target, + path, + profile, + ref deps, + ref local, + config, + compile_kind, + ref rustflags, + .. + } = *self; + let local = local.lock().unwrap(); + ( + rustc, + features, + declared_features, + target, + path, + profile, + &*local, + config, + compile_kind, + rustflags, + ) + .hash(h); + + h.write_usize(deps.len()); + for DepFingerprint { + pkg_id, + name, + public, + fingerprint, + only_requires_rmeta: _, // static property, no need to hash + } in deps + { + pkg_id.hash(h); + name.hash(h); + public.hash(h); + // use memoized dep hashes to avoid exponential blowup + h.write_u64(fingerprint.hash_u64()); + } + } +} + +impl DepFingerprint { + fn new( + build_runner: &mut BuildRunner<'_, '_>, + parent: &Unit, + dep: &UnitDep, + ) -> CargoResult { + let fingerprint = calculate(build_runner, &dep.unit)?; + // We need to be careful about what we hash here. We have a goal of + // supporting renaming a project directory and not rebuilding + // everything. To do that, however, we need to make sure that the cwd + // doesn't make its way into any hashes, and one source of that is the + // `SourceId` for `path` packages. + // + // We already have a requirement that `path` packages all have unique + // names (sort of for this same reason), so if the package source is a + // `path` then we just hash the name, but otherwise we hash the full + // id as it won't change when the directory is renamed. + let pkg_id = if dep.unit.pkg.package_id().source_id().is_path() { + util::hash_u64(dep.unit.pkg.package_id().name()) + } else { + util::hash_u64(dep.unit.pkg.package_id()) + }; + + Ok(DepFingerprint { + pkg_id, + name: dep.extern_crate_name, + public: dep.public, + fingerprint, + only_requires_rmeta: build_runner.only_requires_rmeta(parent, &dep.unit), + }) + } +} + +impl StaleItem { + /// Use the `log` crate to log a hopefully helpful message in diagnosing + /// what file is considered stale and why. This is intended to be used in + /// conjunction with `CARGO_LOG` to determine why Cargo is recompiling + /// something. Currently there's no user-facing usage of this other than + /// that. + fn log(&self) { + match self { + StaleItem::MissingFile(path) => { + info!("stale: missing {:?}", path); + } + StaleItem::UnableToReadFile(path) => { + info!("stale: unable to read {:?}", path); + } + StaleItem::FailedToReadMetadata(path) => { + info!("stale: couldn't read metadata {:?}", path); + } + StaleItem::ChangedFile { + reference, + reference_mtime, + stale, + stale_mtime, + } => { + info!("stale: changed {:?}", stale); + info!(" (vs) {:?}", reference); + info!(" {:?} < {:?}", reference_mtime, stale_mtime); + } + StaleItem::FileSizeChanged { + path, + new_size, + old_size, + } => { + info!("stale: changed {:?}", path); + info!("prior file size {old_size}"); + info!(" new file size {new_size}"); + } + StaleItem::ChangedChecksum { + source, + stored_checksum, + new_checksum, + } => { + info!("stale: changed {:?}", source); + info!("prior checksum {stored_checksum}"); + info!(" new checksum {new_checksum}"); + } + StaleItem::MissingChecksum(path) => { + info!("stale: no prior checksum {:?}", path); + } + StaleItem::ChangedEnv { + var, + previous, + current, + } => { + info!("stale: changed env {:?}", var); + info!(" {:?} != {:?}", previous, current); + } + } + } +} + +/// Calculates the fingerprint for a [`Unit`]. +/// +/// This fingerprint is used by Cargo to learn about when information such as: +/// +/// * A non-path package changes (changes version, changes revision, etc). +/// * Any dependency changes +/// * The compiler changes +/// * The set of features a package is built with changes +/// * The profile a target is compiled with changes (e.g., opt-level changes) +/// * Any other compiler flags change that will affect the result +/// +/// Information like file modification time is only calculated for path +/// dependencies. +fn calculate(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult> { + // This function is slammed quite a lot, so the result is memoized. + if let Some(s) = build_runner.fingerprints.get(unit) { + return Ok(Arc::clone(s)); + } + let mut fingerprint = if unit.mode.is_run_custom_build() { + calculate_run_custom_build(build_runner, unit)? + } else if unit.mode.is_doc_test() { + panic!("doc tests do not fingerprint"); + } else { + calculate_normal(build_runner, unit)? + }; + + // After we built the initial `Fingerprint` be sure to update the + // `fs_status` field of it. + let target_root = target_root(build_runner); + let cargo_exe = build_runner.bcx.gctx.cargo_exe()?; + fingerprint.check_filesystem( + &mut build_runner.mtime_cache, + &mut build_runner.checksum_cache, + &unit.pkg, + &target_root, + cargo_exe, + build_runner.bcx.gctx, + )?; + + let fingerprint = Arc::new(fingerprint); + build_runner + .fingerprints + .insert(unit.clone(), Arc::clone(&fingerprint)); + Ok(fingerprint) +} + +/// Calculate a fingerprint for a "normal" unit, or anything that's not a build +/// script. This is an internal helper of [`calculate`], don't call directly. +fn calculate_normal( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, +) -> CargoResult { + let deps = { + // Recursively calculate the fingerprint for all of our dependencies. + // + // Skip fingerprints of binaries because they don't actually induce a + // recompile, they're just dependencies in the sense that they need to be + // built. The only exception here are artifact dependencies, + // which is an actual dependency that needs a recompile. + // + // Create Vec since mutable build_runner is needed in closure. + let deps = Vec::from(build_runner.unit_deps(unit)); + let mut deps = deps + .into_iter() + .filter(|dep| !dep.unit.target.is_bin() || dep.unit.artifact.is_true()) + .map(|dep| DepFingerprint::new(build_runner, unit, &dep)) + .collect::>>()?; + deps.sort_by(|a, b| a.pkg_id.cmp(&b.pkg_id)); + deps + }; + + // Afterwards calculate our own fingerprint information. + let target_root = target_root(build_runner); + let local = if unit.mode.is_doc() || unit.mode.is_doc_scrape() { + // rustdoc does not have dep-info files. + let fingerprint = pkg_fingerprint(build_runner.bcx, &unit.pkg).with_context(|| { + format!( + "failed to determine package fingerprint for documenting {}", + unit.pkg + ) + })?; + vec![LocalFingerprint::Precalculated(fingerprint)] + } else { + let dep_info = dep_info_loc(build_runner, unit); + let dep_info = dep_info.strip_prefix(&target_root).unwrap().to_path_buf(); + vec![LocalFingerprint::CheckDepInfo { + dep_info, + checksum: build_runner.bcx.gctx.cli_unstable().checksum_freshness, + }] + }; + + // Figure out what the outputs of our unit is, and we'll be storing them + // into the fingerprint as well. + let outputs = build_runner + .outputs(unit)? + .iter() + .filter(|output| !matches!(output.flavor, FileFlavor::DebugInfo | FileFlavor::Auxiliary)) + .map(|output| output.path.clone()) + .collect(); + + // Fill out a bunch more information that we'll be tracking typically + // hashed to take up less space on disk as we just need to know when things + // change. + let extra_flags = if unit.mode.is_doc() || unit.mode.is_doc_scrape() { + &unit.rustdocflags + } else { + &unit.rustflags + } + .to_vec(); + + let profile_hash = util::hash_u64(( + &unit.profile, + unit.mode, + build_runner.bcx.extra_args_for(unit), + build_runner.lto[unit], + unit.pkg.manifest().lint_rustflags(), + )); + let mut config = StableHasher::new(); + if let Some(linker) = build_runner.compilation.target_linker(unit.kind) { + linker.hash(&mut config); + } + if unit.mode.is_doc() && build_runner.bcx.gctx.cli_unstable().rustdoc_map { + if let Ok(map) = build_runner.bcx.gctx.doc_extern_map() { + map.hash(&mut config); + } + } + if let Some(allow_features) = &build_runner.bcx.gctx.cli_unstable().allow_features { + allow_features.hash(&mut config); + } + let compile_kind = unit.kind.fingerprint_hash(); + let mut declared_features = unit.pkg.summary().features().keys().collect::>(); + declared_features.sort(); // to avoid useless rebuild if the user orders it's features + // differently + Ok(Fingerprint { + rustc: util::hash_u64(&build_runner.bcx.rustc().verbose_version), + target: util::hash_u64(&unit.target), + profile: profile_hash, + // Note that .0 is hashed here, not .1 which is the cwd. That doesn't + // actually affect the output artifact so there's no need to hash it. + path: util::hash_u64(path_args(build_runner.bcx.ws, unit).0), + features: format!("{:?}", unit.features), + declared_features: format!("{declared_features:?}"), + deps, + local: Mutex::new(local), + memoized_hash: Mutex::new(None), + config: Hasher::finish(&config), + compile_kind, + rustflags: extra_flags, + fs_status: FsStatus::Stale, + outputs, + }) +} + +/// Calculate a fingerprint for an "execute a build script" unit. This is an +/// internal helper of [`calculate`], don't call directly. +fn calculate_run_custom_build( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, +) -> CargoResult { + assert!(unit.mode.is_run_custom_build()); + // Using the `BuildDeps` information we'll have previously parsed and + // inserted into `build_explicit_deps` built an initial snapshot of the + // `LocalFingerprint` list for this build script. If we previously executed + // the build script this means we'll be watching files and env vars. + // Otherwise if we haven't previously executed it we'll just start watching + // the whole crate. + let (gen_local, overridden) = build_script_local_fingerprints(build_runner, unit)?; + let deps = &build_runner.build_explicit_deps[unit]; + let local = (gen_local)( + deps, + Some(&|| { + const IO_ERR_MESSAGE: &str = "\ +An I/O error happened. Please make sure you can access the file. + +By default, if your project contains a build script, cargo scans all files in +it to determine whether a rebuild is needed. If you don't expect to access the +file, specify `rerun-if-changed` in your build script. +See https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed for more information."; + pkg_fingerprint(build_runner.bcx, &unit.pkg).map_err(|err| { + let mut message = format!("failed to determine package fingerprint for build script for {}", unit.pkg); + if err.root_cause().is::() { + message = format!("{}\n{}", message, IO_ERR_MESSAGE) + } + err.context(message) + }) + }), + )? + .unwrap(); + let output = deps.build_script_output.clone(); + + // Include any dependencies of our execution, which is typically just the + // compilation of the build script itself. (if the build script changes we + // should be rerun!). Note though that if we're an overridden build script + // we have no dependencies so no need to recurse in that case. + let deps = if overridden { + // Overridden build scripts don't need to track deps. + vec![] + } else { + // Create Vec since mutable build_runner is needed in closure. + let deps = Vec::from(build_runner.unit_deps(unit)); + deps.into_iter() + .map(|dep| DepFingerprint::new(build_runner, unit, &dep)) + .collect::>>()? + }; + + let rustflags = unit.rustflags.to_vec(); + + Ok(Fingerprint { + local: Mutex::new(local), + rustc: util::hash_u64(&build_runner.bcx.rustc().verbose_version), + deps, + outputs: if overridden { Vec::new() } else { vec![output] }, + rustflags, + + // Most of the other info is blank here as we don't really include it + // in the execution of the build script, but... this may be a latent + // bug in Cargo. + ..Fingerprint::new() + }) +} + +/// Get ready to compute the [`LocalFingerprint`] values +/// for a [`RunCustomBuild`] unit. +/// +/// This function has, what's on the surface, a seriously wonky interface. +/// You'll call this function and it'll return a closure and a boolean. The +/// boolean is pretty simple in that it indicates whether the `unit` has been +/// overridden via `.cargo/config.toml`. The closure is much more complicated. +/// +/// This closure is intended to capture any local state necessary to compute +/// the `LocalFingerprint` values for this unit. It is `Send` and `'static` to +/// be sent to other threads as well (such as when we're executing build +/// scripts). That deduplication is the rationale for the closure at least. +/// +/// The arguments to the closure are a bit weirder, though, and I'll apologize +/// in advance for the weirdness too. The first argument to the closure is a +/// `&BuildDeps`. This is the parsed version of a build script, and when Cargo +/// starts up this is cached from previous runs of a build script. After a +/// build script executes the output file is reparsed and passed in here. +/// +/// The second argument is the weirdest, it's *optionally* a closure to +/// call [`pkg_fingerprint`]. The `pkg_fingerprint` requires access to +/// "source map" located in `Context`. That's very non-`'static` and +/// non-`Send`, so it can't be used on other threads, such as when we invoke +/// this after a build script has finished. The `Option` allows us to for sure +/// calculate it on the main thread at the beginning, and then swallow the bug +/// for now where a worker thread after a build script has finished doesn't +/// have access. Ideally there would be no second argument or it would be more +/// "first class" and not an `Option` but something that can be sent between +/// threads. In any case, it's a bug for now. +/// +/// This isn't the greatest of interfaces, and if there's suggestions to +/// improve please do so! +/// +/// FIXME(#6779) - see all the words above +/// +/// [`RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild +fn build_script_local_fingerprints( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, +) -> CargoResult<( + Box< + dyn FnOnce( + &BuildDeps, + Option<&dyn Fn() -> CargoResult>, + ) -> CargoResult>> + + Send, + >, + bool, +)> { + assert!(unit.mode.is_run_custom_build()); + // First up, if this build script is entirely overridden, then we just + // return the hash of what we overrode it with. This is the easy case! + if let Some(fingerprint) = build_script_override_fingerprint(build_runner, unit) { + debug!("override local fingerprints deps {}", unit.pkg); + return Ok(( + Box::new( + move |_: &BuildDeps, _: Option<&dyn Fn() -> CargoResult>| { + Ok(Some(vec![fingerprint])) + }, + ), + true, // this is an overridden build script + )); + } + + // ... Otherwise this is a "real" build script and we need to return a real + // closure. Our returned closure classifies the build script based on + // whether it prints `rerun-if-*`. If it *doesn't* print this it's where the + // magical second argument comes into play, which fingerprints a whole + // package. Remember that the fact that this is an `Option` is a bug, but a + // longstanding bug, in Cargo. Recent refactorings just made it painfully + // obvious. + let pkg_root = unit.pkg.root().to_path_buf(); + let target_dir = target_root(build_runner); + let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?); + let calculate = + move |deps: &BuildDeps, pkg_fingerprint: Option<&dyn Fn() -> CargoResult>| { + if deps.rerun_if_changed.is_empty() && deps.rerun_if_env_changed.is_empty() { + match pkg_fingerprint { + // FIXME: this is somewhat buggy with respect to docker and + // weird filesystems. The `Precalculated` variant + // constructed below will, for `path` dependencies, contain + // a stringified version of the mtime for the local crate. + // This violates one of the things we describe in this + // module's doc comment, never hashing mtimes. We should + // figure out a better scheme where a package fingerprint + // may be a string (like for a registry) or a list of files + // (like for a path dependency). Those list of files would + // be stored here rather than the mtime of them. + Some(f) => { + let s = f()?; + debug!( + "old local fingerprints deps {:?} precalculated={:?}", + pkg_root, s + ); + return Ok(Some(vec![LocalFingerprint::Precalculated(s)])); + } + None => return Ok(None), + } + } + + // Ok so now we're in "new mode" where we can have files listed as + // dependencies as well as env vars listed as dependencies. Process + // them all here. + Ok(Some(local_fingerprints_deps( + deps, + &target_dir, + &pkg_root, + &env_config, + ))) + }; + + // Note that `false` == "not overridden" + Ok((Box::new(calculate), false)) +} + +/// Create a [`LocalFingerprint`] for an overridden build script. +/// Returns None if it is not overridden. +fn build_script_override_fingerprint( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, +) -> Option { + // Build script output is only populated at this stage when it is + // overridden. + let build_script_outputs = build_runner.build_script_outputs.lock().unwrap(); + let metadata = build_runner.get_run_build_script_metadata(unit); + // Returns None if it is not overridden. + let output = build_script_outputs.get(metadata)?; + let s = format!( + "overridden build state with hash: {}", + util::hash_u64(output) + ); + Some(LocalFingerprint::Precalculated(s)) +} + +/// Compute the [`LocalFingerprint`] values for a [`RunCustomBuild`] unit for +/// non-overridden new-style build scripts only. This is only used when `deps` +/// is already known to have a nonempty `rerun-if-*` somewhere. +/// +/// [`RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild +fn local_fingerprints_deps( + deps: &BuildDeps, + target_root: &Path, + pkg_root: &Path, + env_config: &Arc>, +) -> Vec { + debug!("new local fingerprints deps {:?}", pkg_root); + let mut local = Vec::new(); + + if !deps.rerun_if_changed.is_empty() { + // Note that like the module comment above says we are careful to never + // store an absolute path in `LocalFingerprint`, so ensure that we strip + // absolute prefixes from them. + let output = deps + .build_script_output + .strip_prefix(target_root) + .unwrap() + .to_path_buf(); + let paths = deps + .rerun_if_changed + .iter() + .map(|p| p.strip_prefix(pkg_root).unwrap_or(p).to_path_buf()) + .collect(); + local.push(LocalFingerprint::RerunIfChanged { output, paths }); + } + + local.extend( + deps.rerun_if_env_changed + .iter() + .map(|s| LocalFingerprint::from_env(s, env_config)), + ); + + local +} + +/// Writes the short fingerprint hash value to `` +/// and logs detailed JSON information to `.json`. +fn write_fingerprint(loc: &Path, fingerprint: &Fingerprint) -> CargoResult<()> { + debug_assert_ne!(fingerprint.rustc, 0); + // fingerprint::new().rustc == 0, make sure it doesn't make it to the file system. + // This is mostly so outside tools can reliably find out what rust version this file is for, + // as we can use the full hash. + let hash = fingerprint.hash_u64(); + debug!("write fingerprint ({:x}) : {}", hash, loc.display()); + paths::write(loc, util::to_hex(hash).as_bytes())?; + + let json = serde_json::to_string(fingerprint).unwrap(); + if cfg!(debug_assertions) { + let f: Fingerprint = serde_json::from_str(&json).unwrap(); + assert_eq!(f.hash_u64(), hash); + } + paths::write(&loc.with_extension("json"), json.as_bytes())?; + Ok(()) +} + +/// Prepare for work when a package starts to build +pub fn prepare_init(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<()> { + let new1 = build_runner.files().fingerprint_dir(unit); + + // Doc tests have no output, thus no fingerprint. + if !new1.exists() && !unit.mode.is_doc_test() { + paths::create_dir_all(&new1)?; + } + + Ok(()) +} + +/// Returns the location that the dep-info file will show up at +/// for the [`Unit`] specified. +pub fn dep_info_loc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> PathBuf { + build_runner.files().fingerprint_file_path(unit, "dep-") +} + +/// Returns an absolute path that target directory. +/// All paths are rewritten to be relative to this. +fn target_root(build_runner: &BuildRunner<'_, '_>) -> PathBuf { + build_runner.bcx.ws.target_dir().into_path_unlocked() +} + +/// Reads the value from the old fingerprint hash file and compare. +/// +/// If dirty, it then restores the detailed information +/// from the fingerprint JSON file, and provides an rich dirty reason. +fn compare_old_fingerprint( + unit: &Unit, + old_hash_path: &Path, + new_fingerprint: &Fingerprint, + mtime_on_use: bool, + forced: bool, +) -> Option { + if mtime_on_use { + // update the mtime so other cleaners know we used it + let t = FileTime::from_system_time(SystemTime::now()); + debug!("mtime-on-use forcing {:?} to {}", old_hash_path, t); + paths::set_file_time_no_err(old_hash_path, t); + } + + let compare = _compare_old_fingerprint(old_hash_path, new_fingerprint); + + match compare.as_ref() { + Ok(None) => {} + Ok(Some(reason)) => { + info!( + "fingerprint dirty for {}/{:?}/{:?}", + unit.pkg, unit.mode, unit.target, + ); + info!(" dirty: {reason:?}"); + } + Err(e) => { + info!( + "fingerprint error for {}/{:?}/{:?}", + unit.pkg, unit.mode, unit.target, + ); + info!(" err: {e:?}"); + } + } + + match compare { + Ok(None) if forced => Some(DirtyReason::Forced), + Ok(reason) => reason, + Err(_) => Some(DirtyReason::FreshBuild), + } +} + +fn _compare_old_fingerprint( + old_hash_path: &Path, + new_fingerprint: &Fingerprint, +) -> CargoResult> { + let old_fingerprint_short = paths::read(old_hash_path)?; + + let new_hash = new_fingerprint.hash_u64(); + + if util::to_hex(new_hash) == old_fingerprint_short && new_fingerprint.fs_status.up_to_date() { + return Ok(None); + } + + let old_fingerprint_json = paths::read(&old_hash_path.with_extension("json"))?; + let old_fingerprint: Fingerprint = serde_json::from_str(&old_fingerprint_json) + .with_context(|| internal("failed to deserialize json"))?; + // Fingerprint can be empty after a failed rebuild (see comment in prepare_target). + if !old_fingerprint_short.is_empty() { + debug_assert_eq!( + util::to_hex(old_fingerprint.hash_u64()), + old_fingerprint_short + ); + } + + Ok(Some(new_fingerprint.compare(&old_fingerprint))) +} + +/// Calculates the fingerprint of a unit thats contains no dep-info files. +fn pkg_fingerprint(bcx: &BuildContext<'_, '_>, pkg: &Package) -> CargoResult { + let source_id = pkg.package_id().source_id(); + let sources = bcx.packages.sources(); + + let source = sources + .get(source_id) + .ok_or_else(|| internal("missing package source"))?; + source.fingerprint(pkg) +} + +/// The `reference` file is considered as "stale" if any file from `paths` has a newer mtime. +fn find_stale_file( + mtime_cache: &mut HashMap, + checksum_cache: &mut HashMap, + reference: &Path, + paths: I, + use_checksums: bool, +) -> Option +where + I: IntoIterator)>, + P: AsRef, +{ + 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() { + let skipable_dirs: Vec<_> = ["git", "registry"] + .into_iter() + .map(|subfolder| cargo_home.join(subfolder)) + .collect(); + Some(skipable_dirs) + } else { + None + }; + for (path, prior_checksum) in paths { + let path = path.as_ref(); + + // Assuming anything in cargo_home/{git, registry} is immutable + // (see also #9455 about marking the src directory readonly) which avoids rebuilds when CI + // caches $CARGO_HOME/registry/{index, cache} and $CARGO_HOME/git/db across runs, keeping + // the content the same but changing the mtime. + if let Some(ref skipable_dirs) = skipable_dirs { + if skipable_dirs.iter().any(|dir| path.starts_with(dir)) { + continue; + } + } + if use_checksums { + let Some((file_len, prior_checksum)) = prior_checksum else { + return Some(StaleItem::MissingChecksum(path.to_path_buf())); + }; + let path_buf = path.to_path_buf(); + + let path_checksum = match checksum_cache.entry(path_buf) { + Entry::Occupied(o) => *o.get(), + Entry::Vacant(v) => { + let Ok(current_file_len) = fs::metadata(&path).map(|m| m.len()) else { + return Some(StaleItem::FailedToReadMetadata(path.to_path_buf())); + }; + if current_file_len != file_len { + return Some(StaleItem::FileSizeChanged { + path: path.to_path_buf(), + new_size: current_file_len, + old_size: file_len, + }); + } + let Ok(file) = File::open(path) else { + return Some(StaleItem::MissingFile(path.to_path_buf())); + }; + let Ok(checksum) = Checksum::compute(prior_checksum.algo(), file) else { + return Some(StaleItem::UnableToReadFile(path.to_path_buf())); + }; + *v.insert(checksum) + } + }; + if path_checksum == prior_checksum { + continue; + } + return Some(StaleItem::ChangedChecksum { + source: path.to_path_buf(), + stored_checksum: prior_checksum, + new_checksum: path_checksum, + }); + } else { + let path_mtime = match mtime_cache.entry(path.to_path_buf()) { + Entry::Occupied(o) => *o.get(), + Entry::Vacant(v) => { + let Ok(mtime) = paths::mtime_recursive(path) else { + return Some(StaleItem::MissingFile(path.to_path_buf())); + }; + *v.insert(mtime) + } + }; + + // TODO: fix #5918. + // Note that equal mtimes should be considered "stale". For filesystems with + // not much timestamp precision like 1s this is would be a conservative approximation + // to handle the case where a file is modified within the same second after + // a build starts. We want to make sure that incremental rebuilds pick that up! + // + // For filesystems with nanosecond precision it's been seen in the wild that + // its "nanosecond precision" isn't really nanosecond-accurate. It turns out that + // kernels may cache the current time so files created at different times actually + // list the same nanosecond precision. Some digging on #5919 picked up that the + // kernel caches the current time between timer ticks, which could mean that if + // a file is updated at most 10ms after a build starts then Cargo may not + // pick up the build changes. + // + // All in all, an equality check here would be a conservative assumption that, + // if equal, files were changed just after a previous build finished. + // Unfortunately this became problematic when (in #6484) cargo switch to more accurately + // measuring the start time of builds. + if path_mtime <= reference_mtime { + continue; + } + + return Some(StaleItem::ChangedFile { + reference: reference.to_path_buf(), + reference_mtime, + stale: path.to_path_buf(), + stale_mtime: path_mtime, + }); + } + } + + debug!( + "all paths up-to-date relative to {:?} mtime={}", + reference, reference_mtime + ); + None +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/future_incompat.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/future_incompat.rs new file mode 100644 index 000000000..abe3de3e2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/future_incompat.rs @@ -0,0 +1,505 @@ +//! Support for [future-incompatible warning reporting][1]. +//! +//! Here is an overview of how Cargo handles future-incompatible reports. +//! +//! ## Receive reports from the compiler +//! +//! When receiving a compiler message during a build, if it is effectively +//! a [`FutureIncompatReport`], Cargo gathers and forwards it as a +//! `Message::FutureIncompatReport` to the main thread. +//! +//! To have the correct layout of strucutures for deserializing a report +//! emitted by the compiler, most of structure definitions, for example +//! [`FutureIncompatReport`], are copied either partially or entirely from +//! [compiler/rustc_errors/src/json.rs][2] in rust-lang/rust repository. +//! +//! ## Persist reports on disk +//! +//! When a build comes to an end, by calling [`save_and_display_report`] +//! Cargo saves the report on disk, and displays it directly if requested +//! via command line or configuration. The information of the on-disk file can +//! be found in [`FUTURE_INCOMPAT_FILE`]. +//! +//! During the persistent process, Cargo will attempt to query the source of +//! each package emitting the report, for the sake of providing an upgrade +//! information as a solution to fix the incompatibility. +//! +//! ## Display reports to users +//! +//! Users can run `cargo report future-incompat` to retrieve a report. This is +//! done by [`OnDiskReports::load`]. Cargo simply prints reports to the +//! standard output. +//! +//! [1]: https://doc.rust-lang.org/nightly/cargo/reference/future-incompat-report.html +//! [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, Workspace}; +use crate::sources::source::QueryKind; +use crate::sources::SourceConfigMap; +use crate::util::cache_lock::CacheLockMode; +use crate::util::CargoResult; +use anyhow::{bail, format_err, Context}; +use serde::{Deserialize, Serialize}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::fmt::Write as _; +use std::io::{Read, Write}; +use std::task::Poll; + +pub const REPORT_PREAMBLE: &str = "\ +The following warnings were discovered during the build. These warnings are an +indication that the packages contain code that will become an error in a +future release of Rust. These warnings typically cover changes to close +soundness problems, unintended or undocumented behavior, or critical problems +that cannot be fixed in a backwards-compatible fashion, and are not expected +to be in wide use. + +Each warning should contain a link for more information on what the warning +means and how to resolve it. +"; + +/// Current version of the on-disk format. +const ON_DISK_VERSION: u32 = 0; + +/// The future incompatibility report, emitted by the compiler as a JSON message. +#[derive(serde::Deserialize)] +pub struct FutureIncompatReport { + pub future_incompat_report: Vec, +} + +/// Structure used for collecting reports in-memory. +pub struct FutureIncompatReportPackage { + pub package_id: PackageId, + pub items: Vec, +} + +/// A single future-incompatible warning emitted by rustc. +#[derive(Serialize, Deserialize)] +pub struct FutureBreakageItem { + /// The date at which this lint will become an error. + /// Currently unused + pub future_breakage_date: Option, + /// The original diagnostic emitted by the compiler + pub diagnostic: Diagnostic, +} + +/// A diagnostic emitted by the compiler as a JSON message. +/// We only care about the 'rendered' field +#[derive(Serialize, Deserialize)] +pub struct Diagnostic { + pub rendered: String, + pub level: String, +} + +/// The filename in the top-level `target` directory where we store +/// the report +const FUTURE_INCOMPAT_FILE: &str = ".future-incompat-report.json"; +/// Max number of reports to save on disk. +const MAX_REPORTS: usize = 5; + +/// The structure saved to disk containing the reports. +#[derive(Serialize, Deserialize)] +pub struct OnDiskReports { + /// A schema version number, to handle older cargo's from trying to read + /// something that they don't understand. + version: u32, + /// The report ID to use for the next report to save. + next_id: u32, + /// Available reports. + reports: Vec, +} + +/// A single report for a given compilation session. +#[derive(Serialize, Deserialize)] +struct OnDiskReport { + /// Unique reference to the report for the `--id` CLI flag. + id: u32, + /// A message describing suggestions for fixing the + /// reported issues + suggestion_message: String, + /// Report, suitable for printing to the console. + /// Maps package names to the corresponding report + /// We use a `BTreeMap` so that the iteration order + /// is stable across multiple runs of `cargo` + per_package: BTreeMap, +} + +impl Default for OnDiskReports { + fn default() -> OnDiskReports { + OnDiskReports { + version: ON_DISK_VERSION, + next_id: 1, + reports: Vec::new(), + } + } +} + +impl OnDiskReports { + /// Saves a new report returning its id + pub fn save_report( + mut self, + ws: &Workspace<'_>, + suggestion_message: String, + per_package_reports: &[FutureIncompatReportPackage], + ) -> u32 { + let per_package = render_report(per_package_reports); + + if let Some(existing_report) = self + .reports + .iter() + .find(|existing| existing.per_package == per_package) + { + return existing_report.id; + } + + let report = OnDiskReport { + id: self.next_id, + suggestion_message, + per_package, + }; + + let saved_id = report.id; + self.next_id += 1; + self.reports.push(report); + if self.reports.len() > MAX_REPORTS { + self.reports.remove(0); + } + let on_disk = serde_json::to_vec(&self).unwrap(); + if let Err(e) = ws + .target_dir() + .open_rw_exclusive_create( + FUTURE_INCOMPAT_FILE, + ws.gctx(), + "Future incompatibility report", + ) + .and_then(|file| { + let mut file = file.file(); + file.set_len(0)?; + file.write_all(&on_disk)?; + Ok(()) + }) + { + crate::display_warning_with_error( + "failed to write on-disk future incompatible report", + &e, + &mut ws.gctx().shell(), + ); + } + + saved_id + } + + /// Loads the on-disk reports. + pub fn load(ws: &Workspace<'_>) -> CargoResult { + let report_file = match ws.target_dir().open_ro_shared( + FUTURE_INCOMPAT_FILE, + ws.gctx(), + "Future incompatible report", + ) { + Ok(r) => r, + Err(e) => { + if let Some(io_err) = e.downcast_ref::() { + if io_err.kind() == std::io::ErrorKind::NotFound { + bail!("no reports are currently available"); + } + } + return Err(e); + } + }; + + let mut file_contents = String::new(); + report_file + .file() + .read_to_string(&mut file_contents) + .context("failed to read report")?; + let on_disk_reports: OnDiskReports = + serde_json::from_str(&file_contents).context("failed to load report")?; + if on_disk_reports.version != ON_DISK_VERSION { + bail!("unable to read reports; reports were saved from a future version of Cargo"); + } + Ok(on_disk_reports) + } + + /// Returns the most recent report ID. + pub fn last_id(&self) -> u32 { + self.reports.last().map(|r| r.id).unwrap() + } + + /// Returns an ANSI-styled report + pub fn get_report(&self, id: u32, package: Option<&str>) -> CargoResult { + let report = self.reports.iter().find(|r| r.id == id).ok_or_else(|| { + let available = itertools::join(self.reports.iter().map(|r| r.id), ", "); + format_err!( + "could not find report with ID {}\n\ + Available IDs are: {}", + id, + available + ) + })?; + + let mut to_display = report.suggestion_message.clone(); + to_display += "\n"; + + let package_report = if let Some(package) = package { + report + .per_package + .get(package) + .ok_or_else(|| { + format_err!( + "could not find package with ID `{}`\n + Available packages are: {}\n + Omit the `--package` flag to display a report for all packages", + package, + itertools::join(report.per_package.keys(), ", ") + ) + })? + .to_string() + } else { + report + .per_package + .values() + .cloned() + .collect::>() + .join("\n") + }; + to_display += &package_report; + + Ok(to_display) + } +} + +fn render_report(per_package_reports: &[FutureIncompatReportPackage]) -> BTreeMap { + let mut report: BTreeMap = BTreeMap::new(); + for per_package in per_package_reports { + let package_spec = format!( + "{}@{}", + per_package.package_id.name(), + per_package.package_id.version() + ); + let rendered = report.entry(package_spec).or_default(); + rendered.push_str(&format!( + "The package `{}` currently triggers the following future incompatibility lints:\n", + per_package.package_id + )); + for item in &per_package.items { + rendered.extend( + item.diagnostic + .rendered + .lines() + .map(|l| format!("> {}\n", l)), + ); + } + } + report +} + +/// Returns a user-readable message explaining which of +/// the packages in `package_ids` have updates available. +/// This is best-effort - if an error occurs, `None` will be returned. +fn get_updates(ws: &Workspace<'_>, package_ids: &BTreeSet) -> Option { + // This in general ignores all errors since this is opportunistic. + let _lock = ws + .gctx() + .acquire_package_cache_lock(CacheLockMode::DownloadExclusive) + .ok()?; + // Create a set of updated registry sources. + let map = SourceConfigMap::new(ws.gctx()).ok()?; + let mut package_ids: BTreeSet<_> = package_ids + .iter() + .filter(|pkg_id| pkg_id.source_id().is_registry()) + .collect(); + let source_ids: HashSet<_> = package_ids + .iter() + .map(|pkg_id| pkg_id.source_id()) + .collect(); + let mut sources: HashMap<_, _> = source_ids + .into_iter() + .filter_map(|sid| { + let source = map.load(sid, &HashSet::new()).ok()?; + Some((sid, source)) + }) + .collect(); + + // Query the sources for new versions, mapping `package_ids` into `summaries`. + let mut summaries = Vec::new(); + while !package_ids.is_empty() { + package_ids.retain(|&pkg_id| { + let Some(source) = sources.get_mut(&pkg_id.source_id()) else { + 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)) => { + summaries.push((pkg_id, sum)); + false + } + Poll::Ready(Err(_)) => false, + Poll::Pending => true, + } + }); + for (_, source) in sources.iter_mut() { + source.block_until_ready().ok()?; + } + } + + let mut updates = String::new(); + for (pkg_id, summaries) in summaries { + let mut updated_versions: Vec<_> = summaries + .iter() + .map(|summary| summary.as_summary().version()) + .filter(|version| *version > pkg_id.version()) + .collect(); + updated_versions.sort(); + + if !updated_versions.is_empty() { + let updated_versions = itertools::join(updated_versions, ", "); + writeln!( + updates, + "{} has the following newer versions available: {}", + pkg_id, updated_versions + ) + .unwrap(); + } + } + Some(updates) +} + +/// Writes a future-incompat report to disk, using the per-package +/// reports gathered during the build. If requested by the user, +/// a message is also displayed in the build output. +pub fn save_and_display_report( + bcx: &BuildContext<'_, '_>, + per_package_future_incompat_reports: &[FutureIncompatReportPackage], +) { + let should_display_message = match bcx.gctx.future_incompat_config() { + Ok(config) => config.should_display_message(), + Err(e) => { + crate::display_warning_with_error( + "failed to read future-incompat config from disk", + &e, + &mut bcx.gctx.shell(), + ); + true + } + }; + + if per_package_future_incompat_reports.is_empty() { + // Explicitly passing a command-line flag overrides + // `should_display_message` from the config file + if bcx.build_config.future_incompat_report { + drop( + bcx.gctx + .shell() + .note("0 dependencies had future-incompatible warnings"), + ); + } + return; + } + + let current_reports = match OnDiskReports::load(bcx.ws) { + Ok(r) => r, + Err(e) => { + tracing::debug!( + "saving future-incompatible reports failed to load current reports: {:?}", + e + ); + OnDiskReports::default() + } + }; + let report_id = current_reports.next_id; + + // Get a list of unique and sorted package name/versions. + let package_ids: BTreeSet<_> = per_package_future_incompat_reports + .iter() + .map(|r| r.package_id) + .collect(); + let package_vers: Vec<_> = package_ids.iter().map(|pid| pid.to_string()).collect(); + + if should_display_message || bcx.build_config.future_incompat_report { + drop(bcx.gctx.shell().warn(&format!( + "the following packages contain code that will be rejected by a future \ + version of Rust: {}", + package_vers.join(", ") + ))); + } + + let updated_versions = get_updates(bcx.ws, &package_ids).unwrap_or(String::new()); + + let update_message = if !updated_versions.is_empty() { + format!( + " +- Some affected dependencies have newer versions available. +You may want to consider updating them to a newer version to see if the issue has been fixed. + +{updated_versions}\n", + updated_versions = updated_versions + ) + } else { + String::new() + }; + + let upstream_info = package_ids + .iter() + .map(|package_id| { + let manifest = bcx.packages.get_one(*package_id).unwrap().manifest(); + format!( + " + - {package_spec} + - Repository: {url} + - Detailed warning command: `cargo report future-incompatibilities --id {id} --package {package_spec}`", + package_spec = format!("{}@{}", package_id.name(), package_id.version()), + url = manifest + .metadata() + .repository + .as_deref() + .unwrap_or(""), + id = report_id, + ) + }) + .collect::>() + .join("\n"); + + let suggestion_message = format!( + " +To solve this problem, you can try the following approaches: + +{update_message} +- If the issue is not solved by updating the dependencies, a fix has to be +implemented by those dependencies. You can help with that by notifying the +maintainers of this problem (e.g. by creating a bug report) or by proposing a +fix to the maintainers (e.g. by creating a pull request): +{upstream_info} + +- If waiting for an upstream fix is not an option, you can use the `[patch]` +section in `Cargo.toml` to use your own version of the dependency. For more +information, see: +https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section + ", + upstream_info = upstream_info, + update_message = update_message, + ); + + let saved_report_id = current_reports.save_report( + bcx.ws, + suggestion_message.clone(), + per_package_future_incompat_reports, + ); + + if bcx.build_config.future_incompat_report { + drop(bcx.gctx.shell().note(&suggestion_message)); + drop(bcx.gctx.shell().note(&format!( + "this report can be shown with `cargo report \ + future-incompatibilities --id {}`", + saved_report_id + ))); + } else if should_display_message { + drop(bcx.gctx.shell().note(&format!( + "to see what the problems were, use the option \ + `--future-incompat-report`, or run `cargo report \ + future-incompatibilities --id {}`", + saved_report_id + ))); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job.rs new file mode 100644 index 000000000..71a9fc418 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job.rs @@ -0,0 +1,114 @@ +//! See [`Job`] and [`Work`]. + +use std::fmt; +use std::mem; + +use super::JobState; +use crate::core::compiler::fingerprint::DirtyReason; +use crate::util::CargoResult; + +/// Represents a unit of [`Work`] with a [`Freshness`] for caller +/// to determine whether to re-execute or not. +pub struct Job { + work: Work, + fresh: Freshness, +} + +/// The basic unit of work. +/// +/// Each proc should send its description before starting. +/// It should send either once or close immediately. +pub struct Work { + inner: Box) -> CargoResult<()> + Send>, +} + +impl Work { + /// Creates a unit of work. + pub fn new(f: F) -> Work + where + F: FnOnce(&JobState<'_, '_>) -> CargoResult<()> + Send + 'static, + { + Work { inner: Box::new(f) } + } + + /// Creates a unit of work that does nothing. + pub fn noop() -> Work { + Work::new(|_| Ok(())) + } + + /// Consumes this work by running it. + pub fn call(self, tx: &JobState<'_, '_>) -> CargoResult<()> { + (self.inner)(tx) + } + + /// Creates a new unit of work that chains `next` after ourself. + pub fn then(self, next: Work) -> Work { + Work::new(move |state| { + self.call(state)?; + next.call(state) + }) + } +} + +impl Job { + /// Creates a new job that does nothing. + pub fn new_fresh() -> Job { + Job { + work: Work::noop(), + fresh: Freshness::Fresh, + } + } + + /// Creates a new job representing a unit of work. + pub fn new_dirty(work: Work, dirty_reason: DirtyReason) -> Job { + Job { + work, + fresh: Freshness::Dirty(dirty_reason), + } + } + + /// Consumes this job by running it, returning the result of the + /// computation. + pub fn run(self, state: &JobState<'_, '_>) -> CargoResult<()> { + self.work.call(state) + } + + /// Returns whether this job was fresh/dirty, where "fresh" means we're + /// likely to perform just some small bookkeeping where "dirty" means we'll + /// probably do something slow like invoke rustc. + pub fn freshness(&self) -> &Freshness { + &self.fresh + } + + /// Chains the given work by putting it in front of our own unit of work. + pub fn before(&mut self, next: Work) { + let prev = mem::replace(&mut self.work, Work::noop()); + self.work = next.then(prev); + } +} + +impl fmt::Debug for Job { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Job {{ ... }}") + } +} + +/// Indication of the freshness of a package. +/// +/// A fresh package does not necessarily need to be rebuilt (unless a dependency +/// was also rebuilt), and a dirty package must always be rebuilt. +#[derive(Debug, Clone)] +pub enum Freshness { + Fresh, + Dirty(DirtyReason), +} + +impl Freshness { + pub fn is_dirty(&self) -> bool { + matches!(self, Freshness::Dirty(_)) + } + + pub fn is_fresh(&self) -> bool { + matches!(self, Freshness::Fresh) + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job_state.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job_state.rs new file mode 100644 index 000000000..b3b2e8960 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/job_state.rs @@ -0,0 +1,200 @@ +//! See [`JobState`]. + +use std::{cell::Cell, marker, sync::Arc}; + +use cargo_util::ProcessBuilder; + +use crate::core::compiler::build_runner::OutputFile; +use crate::core::compiler::future_incompat::FutureBreakageItem; +use crate::util::Queue; +use crate::CargoResult; + +use super::{Artifact, DiagDedupe, Job, JobId, Message}; + +/// A `JobState` is constructed by `JobQueue::run` and passed to `Job::run`. It includes everything +/// necessary to communicate between the main thread and the execution of the job. +/// +/// The job may execute on either a dedicated thread or the main thread. If the job executes on the +/// main thread, the `output` field must be set to prevent a deadlock. +pub struct JobState<'a, 'gctx> { + /// Channel back to the main thread to coordinate messages and such. + /// + /// When the `output` field is `Some`, care must be taken to avoid calling `push_bounded` on + /// the message queue to prevent a deadlock. + messages: Arc>, + + /// Normally output is sent to the job queue with backpressure. When the job is fresh + /// however we need to immediately display the output to prevent a deadlock as the + /// output messages are processed on the same thread as they are sent from. `output` + /// defines where to output in this case. + /// + /// Currently the [`Shell`] inside [`GlobalContext`] is wrapped in a `RefCell` and thus can't + /// be passed between threads. This means that it isn't possible for multiple output messages + /// to be interleaved. In the future, it may be wrapped in a `Mutex` instead. In this case + /// interleaving is still prevented as the lock would be held for the whole printing of an + /// output message. + /// + /// [`Shell`]: crate::core::Shell + /// [`GlobalContext`]: crate::GlobalContext + output: Option<&'a DiagDedupe<'gctx>>, + + /// The job id that this state is associated with, used when sending + /// messages back to the main thread. + id: JobId, + + /// Whether or not we're expected to have a call to `rmeta_produced`. Once + /// that method is called this is dynamically set to `false` to prevent + /// sending a double message later on. + rmeta_required: Cell, + + // Historical versions of Cargo made use of the `'a` argument here, so to + // leave the door open to future refactorings keep it here. + _marker: marker::PhantomData<&'a ()>, +} + +impl<'a, 'gctx> JobState<'a, 'gctx> { + pub(super) fn new( + id: JobId, + messages: Arc>, + output: Option<&'a DiagDedupe<'gctx>>, + rmeta_required: bool, + ) -> Self { + Self { + id, + messages, + output, + rmeta_required: Cell::new(rmeta_required), + _marker: marker::PhantomData, + } + } + + pub fn running(&self, cmd: &ProcessBuilder) { + self.messages.push(Message::Run(self.id, cmd.to_string())); + } + + pub fn build_plan( + &self, + module_name: String, + cmd: ProcessBuilder, + filenames: Arc>, + ) { + self.messages + .push(Message::BuildPlanMsg(module_name, cmd, filenames)); + } + + pub fn stdout(&self, stdout: String) -> CargoResult<()> { + if let Some(dedupe) = self.output { + writeln!(dedupe.gctx.shell().out(), "{}", stdout)?; + } else { + self.messages.push_bounded(Message::Stdout(stdout)); + } + Ok(()) + } + + pub fn stderr(&self, stderr: String) -> CargoResult<()> { + if let Some(dedupe) = self.output { + let mut shell = dedupe.gctx.shell(); + shell.print_ansi_stderr(stderr.as_bytes())?; + shell.err().write_all(b"\n")?; + } else { + self.messages.push_bounded(Message::Stderr(stderr)); + } + Ok(()) + } + + /// See [`Message::Diagnostic`] and [`Message::WarningCount`]. + pub fn emit_diag(&self, level: &str, diag: String, fixable: bool) -> CargoResult<()> { + if let Some(dedupe) = self.output { + let emitted = dedupe.emit_diag(&diag)?; + if level == "warning" { + self.messages.push(Message::WarningCount { + id: self.id, + emitted, + fixable, + }); + } + } else { + self.messages.push_bounded(Message::Diagnostic { + id: self.id, + level: level.to_string(), + diag, + fixable, + }); + } + Ok(()) + } + + /// See [`Message::Warning`]. + pub fn warning(&self, warning: String) -> CargoResult<()> { + self.messages.push_bounded(Message::Warning { + id: self.id, + warning, + }); + Ok(()) + } + + /// A method used to signal to the coordinator thread that the rmeta file + /// for an rlib has been produced. This is only called for some rmeta + /// builds when required, and can be called at any time before a job ends. + /// This should only be called once because a metadata file can only be + /// produced once! + pub fn rmeta_produced(&self) { + self.rmeta_required.set(false); + self.messages + .push(Message::Finish(self.id, Artifact::Metadata, Ok(()))); + } + + /// Drives a [`Job`] to finish. This ensures that a [`Message::Finish`] is + /// sent even if our job panics. + pub(super) fn run_to_finish(self, job: Job) { + let mut sender = FinishOnDrop { + messages: &self.messages, + id: self.id, + result: None, + }; + sender.result = Some(job.run(&self)); + + // If the `rmeta_required` wasn't consumed but it was set + // previously, then we either have: + // + // 1. The `job` didn't do anything because it was "fresh". + // 2. The `job` returned an error and didn't reach the point where + // it called `rmeta_produced`. + // 3. We forgot to call `rmeta_produced` and there's a bug in Cargo. + // + // Ruling out the third, the other two are pretty common for 2 + // we'll just naturally abort the compilation operation but for 1 + // we need to make sure that the metadata is flagged as produced so + // send a synthetic message here. + if self.rmeta_required.get() && sender.result.as_ref().unwrap().is_ok() { + self.messages + .push(Message::Finish(self.id, Artifact::Metadata, Ok(()))); + } + + // Use a helper struct with a `Drop` implementation to guarantee + // that a `Finish` message is sent even if our job panics. We + // shouldn't panic unless there's a bug in Cargo, so we just need + // to make sure nothing hangs by accident. + struct FinishOnDrop<'a> { + messages: &'a Queue, + id: JobId, + result: Option>, + } + + impl Drop for FinishOnDrop<'_> { + fn drop(&mut self) { + let result = self + .result + .take() + .unwrap_or_else(|| Err(anyhow::format_err!("worker panicked"))); + self.messages + .push(Message::Finish(self.id, Artifact::All, result)); + } + } + } + + pub fn future_incompat_report(&self, report: Vec) { + self.messages + .push(Message::FutureIncompatReport(self.id, report)); + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/mod.rs new file mode 100644 index 000000000..7ab12a3a2 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/job_queue/mod.rs @@ -0,0 +1,1230 @@ +//! Management of the interaction between the main `cargo` and all spawned jobs. +//! +//! ## Overview +//! +//! This module implements a job queue. A job here represents a unit of work, +//! which is roughly a rustc invocation, a build script run, or just a no-op. +//! The job queue primarily handles the following things: +//! +//! * Spawns concurrent jobs. Depending on its [`Freshness`], a job could be +//! either executed on a spawned thread or ran on the same thread to avoid +//! the threading overhead. +//! * Controls the number of concurrency. It allocates and manages [`jobserver`] +//! tokens to each spawned off rustc and build scripts. +//! * Manages the communication between the main `cargo` process and its +//! spawned jobs. Those [`Message`]s are sent over a [`Queue`] shared +//! across threads. +//! * Schedules the execution order of each [`Job`]. Priorities are determined +//! when calling [`JobQueue::enqueue`] to enqueue a job. The scheduling is +//! relatively rudimentary and could likely be improved. +//! +//! A rough outline of building a queue and executing jobs is: +//! +//! 1. [`JobQueue::new`] to simply create one queue. +//! 2. [`JobQueue::enqueue`] to add new jobs onto the queue. +//! 3. Consumes the queue and executes all jobs via [`JobQueue::execute`]. +//! +//! The primary loop happens insides [`JobQueue::execute`], which is effectively +//! [`DrainState::drain_the_queue`]. [`DrainState`] is, as its name tells, +//! the running state of the job queue getting drained. +//! +//! ## Jobserver +//! +//! As of Feb. 2023, Cargo and rustc have a relatively simple jobserver +//! relationship with each other. They share a single jobserver amongst what +//! is potentially hundreds of threads of work on many-cored systems. +//! The jobserver could come from either the environment (e.g., from a `make` +//! invocation), or from Cargo creating its own jobserver server if there is no +//! jobserver to inherit from. +//! +//! Cargo wants to complete the build as quickly as possible, fully saturating +//! all cores (as constrained by the `-j=N`) parameter. Cargo also must not spawn +//! more than N threads of work: the total amount of tokens we have floating +//! around must always be limited to N. +//! +//! It is not really possible to optimally choose which crate should build +//! first or last; nor is it possible to decide whether to give an additional +//! token to rustc first or rather spawn a new crate of work. The algorithm in +//! Cargo prioritizes spawning as many crates (i.e., rustc processes) as +//! possible. In short, the jobserver relationship among Cargo and rustc +//! processes is **1 `cargo` to N `rustc`**. Cargo knows nothing beyond rustc +//! processes in terms of parallelism[^parallel-rustc]. +//! +//! We integrate with the [jobserver] crate, originating from GNU make +//! [POSIX jobserver], to make sure that build scripts which use make to +//! build C code can cooperate with us on the number of used tokens and +//! avoid overfilling the system we're on. +//! +//! ## Scheduling +//! +//! The current scheduling algorithm is not really polished. It is simply based +//! on a dependency graph [`DependencyQueue`]. We continue adding nodes onto +//! the graph until we finalize it. When the graph gets finalized, it finds the +//! sum of the cost of each dependencies of each node, including transitively. +//! The sum of dependency cost turns out to be the cost of each given node. +//! +//! At the time being, the cost is just passed as a fixed placeholder in +//! [`JobQueue::enqueue`]. In the future, we could explore more possibilities +//! around it. For instance, we start persisting timing information for each +//! build somewhere. For a subsequent build, we can look into the historical +//! data and perform a PGO-like optimization to prioritize jobs, making a build +//! fully pipelined. +//! +//! ## Message queue +//! +//! Each spawned thread running a process uses the message queue [`Queue`] to +//! send messages back to the main thread (the one running `cargo`). +//! The main thread coordinates everything, and handles printing output. +//! +//! It is important to be careful which messages use [`push`] vs [`push_bounded`]. +//! `push` is for priority messages (like tokens, or "finished") where the +//! sender shouldn't block. We want to handle those so real work can proceed +//! ASAP. +//! +//! `push_bounded` is only for messages being printed to stdout/stderr. Being +//! bounded prevents a flood of messages causing a large amount of memory +//! being used. +//! +//! `push` also avoids blocking which helps avoid deadlocks. For example, when +//! the diagnostic server thread is dropped, it waits for the thread to exit. +//! But if the thread is blocked on a full queue, and there is a critical +//! error, the drop will deadlock. This should be fixed at some point in the +//! future. The jobserver thread has a similar problem, though it will time +//! out after 1 second. +//! +//! To access the message queue, each running `Job` is given its own [`JobState`], +//! containing everything it needs to communicate with the main thread. +//! +//! See [`Message`] for all available message kinds. +//! +//! [^parallel-rustc]: In fact, `jobserver` that Cargo uses also manages the +//! allocation of tokens to rustc beyond the implicit token each rustc owns +//! (i.e., the ones used for parallel LLVM work and parallel rustc threads). +//! See also ["Rust Compiler Development Guide: Parallel Compilation"] +//! and [this comment][rustc-codegen] in rust-lang/rust. +//! +//! ["Rust Compiler Development Guide: Parallel Compilation"]: https://rustc-dev-guide.rust-lang.org/parallel-rustc.html +//! [rustc-codegen]: https://github.com/rust-lang/rust/blob/5423745db8b434fcde54888b35f518f00cce00e4/compiler/rustc_codegen_ssa/src/back/write.rs#L1204-L1217 +//! [jobserver]: https://docs.rs/jobserver +//! [POSIX jobserver]: https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html +//! [`push`]: Queue::push +//! [`push_bounded`]: Queue::push_bounded + +mod job; +mod job_state; + +use std::cell::RefCell; +use std::collections::{HashMap, HashSet}; +use std::fmt::Write as _; +use std::io; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use std::thread::{self, Scope}; +use std::time::Duration; + +use anyhow::{format_err, Context as _}; +use cargo_util::ProcessBuilder; +use jobserver::{Acquired, HelperThread}; +use semver::Version; +use tracing::{debug, trace}; + +pub use self::job::Freshness::{self, Dirty, Fresh}; +pub use self::job::{Job, Work}; +pub use self::job_state::JobState; +use super::build_runner::OutputFile; +use super::custom_build::Severity; +use super::timings::Timings; +use super::{BuildContext, BuildPlan, BuildRunner, CompileMode, Unit}; +use crate::core::compiler::descriptive_pkg_name; +use crate::core::compiler::future_incompat::{ + self, FutureBreakageItem, FutureIncompatReportPackage, +}; +use crate::core::resolver::ResolveBehavior; +use crate::core::{PackageId, Shell, TargetKind}; +use crate::util::context::WarningHandling; +use crate::util::diagnostic_server::{self, DiagnosticPrinter}; +use crate::util::errors::AlreadyPrintedError; +use crate::util::machine_message::{self, Message as _}; +use crate::util::CargoResult; +use crate::util::{self, internal}; +use crate::util::{DependencyQueue, GlobalContext, Progress, ProgressStyle, Queue}; + +/// This structure is backed by the `DependencyQueue` type and manages the +/// queueing of compilation steps for each package. Packages enqueue units of +/// work and then later on the entire graph is converted to `DrainState` and +/// executed. +pub struct JobQueue<'gctx> { + queue: DependencyQueue, + counts: HashMap, + timings: Timings<'gctx>, +} + +/// This structure is backed by the `DependencyQueue` type and manages the +/// actual compilation step of each package. Packages enqueue units of work and +/// then later on the entire graph is processed and compiled. +/// +/// It is created from `JobQueue` when we have fully assembled the crate graph +/// (i.e., all package dependencies are known). +struct DrainState<'gctx> { + // This is the length of the DependencyQueue when starting out + total_units: usize, + + queue: DependencyQueue, + messages: Arc>, + /// Diagnostic deduplication support. + diag_dedupe: DiagDedupe<'gctx>, + /// Count of warnings, used to print a summary after the job succeeds + warning_count: HashMap, + active: HashMap, + compiled: HashSet, + documented: HashSet, + scraped: HashSet, + counts: HashMap, + progress: Progress<'gctx>, + next_id: u32, + timings: Timings<'gctx>, + + /// Tokens that are currently owned by this Cargo, and may be "associated" + /// with a rustc process. They may also be unused, though if so will be + /// dropped on the next loop iteration. + /// + /// Note that the length of this may be zero, but we will still spawn work, + /// as we share the implicit token given to this Cargo process with a + /// single rustc process. + tokens: Vec, + + /// The list of jobs that we have not yet started executing, but have + /// retrieved from the `queue`. We eagerly pull jobs off the main queue to + /// allow us to request jobserver tokens pretty early. + pending_queue: Vec<(Unit, Job, usize)>, + print: DiagnosticPrinter<'gctx>, + + /// How many jobs we've finished + finished: usize, + per_package_future_incompat_reports: Vec, +} + +/// Count of warnings, used to print a summary after the job succeeds +#[derive(Default)] +pub struct WarningCount { + /// total number of warnings + pub total: usize, + /// number of warnings that were suppressed because they + /// were duplicates of a previous warning + pub duplicates: usize, + /// number of fixable warnings set to `NotAllowed` + /// if any errors have been seen ofr the current + /// target + pub fixable: FixableWarnings, +} + +impl WarningCount { + /// If an error is seen this should be called + /// to set `fixable` to `NotAllowed` + fn disallow_fixable(&mut self) { + self.fixable = FixableWarnings::NotAllowed; + } + + /// Checks fixable if warnings are allowed + /// fixable warnings are allowed if no + /// errors have been seen for the current + /// target. If an error was seen `fixable` + /// will be `NotAllowed`. + fn fixable_allowed(&self) -> bool { + match &self.fixable { + FixableWarnings::NotAllowed => false, + _ => true, + } + } +} + +/// Used to keep track of how many fixable warnings there are +/// and if fixable warnings are allowed +#[derive(Default)] +pub enum FixableWarnings { + NotAllowed, + #[default] + Zero, + Positive(usize), +} + +pub struct ErrorsDuringDrain { + pub count: usize, +} + +struct ErrorToHandle { + error: anyhow::Error, + + /// This field is true for "interesting" errors and false for "mundane" + /// errors. If false, we print the above error only if it's the first one + /// encountered so far while draining the job queue. + /// + /// At most places that an error is propagated, we set this to false to + /// avoid scenarios where Cargo might end up spewing tons of redundant error + /// messages. For example if an i/o stream got closed somewhere, we don't + /// care about individually reporting every thread that it broke; just the + /// first is enough. + /// + /// The exception where `print_always` is true is that we do report every + /// instance of a rustc invocation that failed with diagnostics. This + /// corresponds to errors from `Message::Finish`. + print_always: bool, +} + +impl From for ErrorToHandle +where + anyhow::Error: From, +{ + fn from(error: E) -> Self { + ErrorToHandle { + error: anyhow::Error::from(error), + print_always: false, + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct JobId(pub u32); + +impl std::fmt::Display for JobId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +/// Handler for deduplicating diagnostics. +struct DiagDedupe<'gctx> { + seen: RefCell>, + gctx: &'gctx GlobalContext, +} + +impl<'gctx> DiagDedupe<'gctx> { + fn new(gctx: &'gctx GlobalContext) -> Self { + DiagDedupe { + seen: RefCell::new(HashSet::new()), + gctx, + } + } + + /// Emits a diagnostic message. + /// + /// Returns `true` if the message was emitted, or `false` if it was + /// suppressed for being a duplicate. + fn emit_diag(&self, diag: &str) -> CargoResult { + let h = util::hash_u64(diag); + if !self.seen.borrow_mut().insert(h) { + return Ok(false); + } + let mut shell = self.gctx.shell(); + shell.print_ansi_stderr(diag.as_bytes())?; + shell.err().write_all(b"\n")?; + Ok(true) + } +} + +/// Possible artifacts that can be produced by compilations, used as edge values +/// in the dependency graph. +/// +/// As edge values we can have multiple kinds of edges depending on one node, +/// for example some units may only depend on the metadata for an rlib while +/// others depend on the full rlib. This `Artifact` enum is used to distinguish +/// this case and track the progress of compilations as they proceed. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +enum Artifact { + /// A generic placeholder for "depends on everything run by a step" and + /// means that we can't start the next compilation until the previous has + /// finished entirely. + All, + + /// A node indicating that we only depend on the metadata of a compilation, + /// but the compilation is typically also producing an rlib. We can start + /// our step, however, before the full rlib is available. + Metadata, +} + +enum Message { + Run(JobId, String), + BuildPlanMsg(String, ProcessBuilder, Arc>), + Stdout(String), + Stderr(String), + + // This is for general stderr output from subprocesses + Diagnostic { + id: JobId, + level: String, + diag: String, + fixable: bool, + }, + // This handles duplicate output that is suppressed, for showing + // only a count of duplicate messages instead + WarningCount { + id: JobId, + emitted: bool, + fixable: bool, + }, + // This is for warnings generated by Cargo's interpretation of the + // subprocess output, e.g. scrape-examples prints a warning if a + // unit fails to be scraped + Warning { + id: JobId, + warning: String, + }, + + FixDiagnostic(diagnostic_server::Message), + Token(io::Result), + Finish(JobId, Artifact, CargoResult<()>), + FutureIncompatReport(JobId, Vec), +} + +impl<'gctx> JobQueue<'gctx> { + pub fn new(bcx: &BuildContext<'_, 'gctx>) -> JobQueue<'gctx> { + JobQueue { + queue: DependencyQueue::new(), + counts: HashMap::new(), + timings: Timings::new(bcx, &bcx.roots), + } + } + + pub fn enqueue( + &mut self, + build_runner: &BuildRunner<'_, 'gctx>, + unit: &Unit, + job: Job, + ) -> CargoResult<()> { + let dependencies = build_runner.unit_deps(unit); + let mut queue_deps = dependencies + .iter() + .filter(|dep| { + // Binaries aren't actually needed to *compile* tests, just to run + // them, so we don't include this dependency edge in the job graph. + // But we shouldn't filter out dependencies being scraped for Rustdoc. + (!dep.unit.target.is_test() && !dep.unit.target.is_bin()) + || dep.unit.artifact.is_true() + || dep.unit.mode.is_doc_scrape() + }) + .map(|dep| { + // Handle the case here where our `unit -> dep` dependency may + // only require the metadata, not the full compilation to + // finish. Use the tables in `build_runner` to figure out what + // kind of artifact is associated with this dependency. + let artifact = if build_runner.only_requires_rmeta(unit, &dep.unit) { + Artifact::Metadata + } else { + Artifact::All + }; + (dep.unit.clone(), artifact) + }) + .collect::>(); + + // This is somewhat tricky, but we may need to synthesize some + // dependencies for this target if it requires full upstream + // compilations to have completed. Because of pipelining, some + // dependency edges may be `Metadata` due to the above clause (as + // opposed to everything being `All`). For example consider: + // + // a (binary) + // └ b (lib) + // └ c (lib) + // + // Here the dependency edge from B to C will be `Metadata`, and the + // dependency edge from A to B will be `All`. For A to be compiled, + // however, it currently actually needs the full rlib of C. This means + // that we need to synthesize a dependency edge for the dependency graph + // from A to C. That's done here. + // + // This will walk all dependencies of the current target, and if any of + // *their* dependencies are `Metadata` then we depend on the `All` of + // the target as well. This should ensure that edges changed to + // `Metadata` propagate upwards `All` dependencies to anything that + // transitively contains the `Metadata` edge. + if unit.requires_upstream_objects() { + for dep in dependencies { + depend_on_deps_of_deps(build_runner, &mut queue_deps, dep.unit.clone()); + } + + fn depend_on_deps_of_deps( + build_runner: &BuildRunner<'_, '_>, + deps: &mut HashMap, + unit: Unit, + ) { + for dep in build_runner.unit_deps(&unit) { + if deps.insert(dep.unit.clone(), Artifact::All).is_none() { + depend_on_deps_of_deps(build_runner, deps, dep.unit.clone()); + } + } + } + } + + // For now we use a fixed placeholder value for the cost of each unit, but + // in the future this could be used to allow users to provide hints about + // relative expected costs of units, or this could be automatically set in + // a smarter way using timing data from a previous compilation. + self.queue.queue(unit.clone(), job, queue_deps, 100); + *self.counts.entry(unit.pkg.package_id()).or_insert(0) += 1; + Ok(()) + } + + /// Executes all jobs necessary to build the dependency graph. + /// + /// This function will spawn off `config.jobs()` workers to build all of the + /// necessary dependencies, in order. Freshness is propagated as far as + /// possible along each dependency chain. + #[tracing::instrument(skip_all)] + pub fn execute( + mut self, + build_runner: &mut BuildRunner<'_, '_>, + plan: &mut BuildPlan, + ) -> CargoResult<()> { + self.queue.queue_finished(); + + let progress = + Progress::with_style("Building", ProgressStyle::Ratio, build_runner.bcx.gctx); + let state = DrainState { + total_units: self.queue.len(), + queue: self.queue, + // 100 here is somewhat arbitrary. It is a few screenfulls of + // output, and hopefully at most a few megabytes of memory for + // typical messages. If you change this, please update the test + // caching_large_output, too. + messages: Arc::new(Queue::new(100)), + diag_dedupe: DiagDedupe::new(build_runner.bcx.gctx), + warning_count: HashMap::new(), + active: HashMap::new(), + compiled: HashSet::new(), + documented: HashSet::new(), + scraped: HashSet::new(), + counts: self.counts, + progress, + next_id: 0, + timings: self.timings, + tokens: Vec::new(), + pending_queue: Vec::new(), + print: DiagnosticPrinter::new( + build_runner.bcx.gctx, + &build_runner.bcx.rustc().workspace_wrapper, + ), + finished: 0, + per_package_future_incompat_reports: Vec::new(), + }; + + // Create a helper thread for acquiring jobserver tokens + let messages = state.messages.clone(); + let helper = build_runner + .jobserver + .clone() + .into_helper_thread(move |token| { + messages.push(Message::Token(token)); + }) + .context("failed to create helper thread for jobserver management")?; + + // Create a helper thread to manage the diagnostics for rustfix if + // necessary. + let messages = state.messages.clone(); + // It is important that this uses `push` instead of `push_bounded` for + // now. If someone wants to fix this to be bounded, the `drop` + // implementation needs to be changed to avoid possible deadlocks. + let _diagnostic_server = build_runner + .bcx + .build_config + .rustfix_diagnostic_server + .borrow_mut() + .take() + .map(move |srv| srv.start(move |msg| messages.push(Message::FixDiagnostic(msg)))); + + thread::scope(move |scope| { + match state.drain_the_queue(build_runner, plan, scope, &helper) { + Some(err) => Err(err), + None => Ok(()), + } + }) + } +} + +impl<'gctx> DrainState<'gctx> { + fn spawn_work_if_possible<'s>( + &mut self, + build_runner: &mut BuildRunner<'_, '_>, + jobserver_helper: &HelperThread, + scope: &'s Scope<'s, '_>, + ) -> CargoResult<()> { + // Dequeue as much work as we can, learning about everything + // possible that can run. Note that this is also the point where we + // start requesting job tokens. Each job after the first needs to + // request a token. + while let Some((unit, job, priority)) = self.queue.dequeue() { + // We want to keep the pieces of work in the `pending_queue` sorted + // by their priorities, and insert the current job at its correctly + // sorted position: following the lower priority jobs, and the ones + // with the same priority (since they were dequeued before the + // current one, we also keep that relation). + let idx = self + .pending_queue + .partition_point(|&(_, _, p)| p <= priority); + self.pending_queue.insert(idx, (unit, job, priority)); + if self.active.len() + self.pending_queue.len() > 1 { + jobserver_helper.request_token(); + } + } + + // Now that we've learned of all possible work that we can execute + // try to spawn it so long as we've got a jobserver token which says + // we're able to perform some parallel work. + // The `pending_queue` is sorted in ascending priority order, and we + // remove items from its end to schedule the highest priority items + // sooner. + while self.has_extra_tokens() && !self.pending_queue.is_empty() { + let (unit, job, _) = self.pending_queue.pop().unwrap(); + *self.counts.get_mut(&unit.pkg.package_id()).unwrap() -= 1; + if !build_runner.bcx.build_config.build_plan { + // Print out some nice progress information. + // NOTE: An error here will drop the job without starting it. + // That should be OK, since we want to exit as soon as + // possible during an error. + self.note_working_on( + build_runner.bcx.gctx, + build_runner.bcx.ws.root(), + &unit, + job.freshness(), + )?; + } + self.run(&unit, job, build_runner, scope); + } + + Ok(()) + } + + fn has_extra_tokens(&self) -> bool { + self.active.len() < self.tokens.len() + 1 + } + + fn handle_event( + &mut self, + build_runner: &mut BuildRunner<'_, '_>, + plan: &mut BuildPlan, + event: Message, + ) -> Result<(), ErrorToHandle> { + let warning_handling = build_runner.bcx.gctx.warning_handling()?; + match event { + Message::Run(id, cmd) => { + build_runner + .bcx + .gctx + .shell() + .verbose(|c| c.status("Running", &cmd))?; + self.timings.unit_start(id, self.active[&id].clone()); + } + Message::BuildPlanMsg(module_name, cmd, filenames) => { + plan.update(&module_name, &cmd, &filenames)?; + } + Message::Stdout(out) => { + writeln!(build_runner.bcx.gctx.shell().out(), "{}", out)?; + } + Message::Stderr(err) => { + let mut shell = build_runner.bcx.gctx.shell(); + shell.print_ansi_stderr(err.as_bytes())?; + shell.err().write_all(b"\n")?; + } + Message::Diagnostic { + id, + level, + diag, + fixable, + } => { + let emitted = self.diag_dedupe.emit_diag(&diag)?; + if level == "warning" { + self.bump_warning_count(id, emitted, fixable); + } + if level == "error" { + let cnts = self.warning_count.entry(id).or_default(); + // If there is an error, the `cargo fix` message should not show + cnts.disallow_fixable(); + } + } + Message::Warning { id, warning } => { + if warning_handling != WarningHandling::Allow { + build_runner.bcx.gctx.shell().warn(warning)?; + } + self.bump_warning_count(id, true, false); + } + Message::WarningCount { + id, + emitted, + fixable, + } => { + self.bump_warning_count(id, emitted, fixable); + } + Message::FixDiagnostic(msg) => { + self.print.print(&msg)?; + } + Message::Finish(id, artifact, result) => { + let unit = match artifact { + // If `id` has completely finished we remove it + // from the `active` map ... + Artifact::All => { + trace!("end: {:?}", id); + self.finished += 1; + self.report_warning_count( + build_runner, + id, + &build_runner.bcx.rustc().workspace_wrapper, + ); + self.active.remove(&id).unwrap() + } + // ... otherwise if it hasn't finished we leave it + // in there as we'll get another `Finish` later on. + Artifact::Metadata => { + trace!("end (meta): {:?}", id); + self.active[&id].clone() + } + }; + debug!("end ({:?}): {:?}", unit, result); + match result { + Ok(()) => self.finish(id, &unit, artifact, build_runner)?, + Err(_) if build_runner.bcx.unit_can_fail_for_docscraping(&unit) => { + build_runner + .failed_scrape_units + .lock() + .unwrap() + .insert(build_runner.files().metadata(&unit).unit_id()); + self.queue.finish(&unit, &artifact); + } + Err(error) => { + let show_warnings = true; + self.emit_log_messages(&unit, build_runner, show_warnings)?; + self.back_compat_notice(build_runner, &unit)?; + return Err(ErrorToHandle { + error, + print_always: true, + }); + } + } + } + Message::FutureIncompatReport(id, items) => { + let package_id = self.active[&id].pkg.package_id(); + self.per_package_future_incompat_reports + .push(FutureIncompatReportPackage { package_id, items }); + } + Message::Token(acquired_token) => { + let token = acquired_token.context("failed to acquire jobserver token")?; + self.tokens.push(token); + } + } + + Ok(()) + } + + // This will also tick the progress bar as appropriate + fn wait_for_events(&mut self) -> Vec { + // Drain all events at once to avoid displaying the progress bar + // unnecessarily. If there's no events we actually block waiting for + // an event, but we keep a "heartbeat" going to allow `record_cpu` + // to run above to calculate CPU usage over time. To do this we + // listen for a message with a timeout, and on timeout we run the + // previous parts of the loop again. + let mut events = self.messages.try_pop_all(); + if events.is_empty() { + loop { + self.tick_progress(); + self.tokens.truncate(self.active.len() - 1); + match self.messages.pop(Duration::from_millis(500)) { + Some(message) => { + events.push(message); + break; + } + None => continue, + } + } + } + events + } + + /// This is the "main" loop, where Cargo does all work to run the + /// compiler. + /// + /// This returns an Option to prevent the use of `?` on `Result` types + /// because it is important for the loop to carefully handle errors. + fn drain_the_queue<'s>( + mut self, + build_runner: &mut BuildRunner<'_, '_>, + plan: &mut BuildPlan, + scope: &'s Scope<'s, '_>, + jobserver_helper: &HelperThread, + ) -> Option { + trace!("queue: {:#?}", self.queue); + + // Iteratively execute the entire dependency graph. Each turn of the + // loop starts out by scheduling as much work as possible (up to the + // maximum number of parallel jobs we have tokens for). A local queue + // is maintained separately from the main dependency queue as one + // dequeue may actually dequeue quite a bit of work (e.g., 10 binaries + // in one package). + // + // After a job has finished we update our internal state if it was + // successful and otherwise wait for pending work to finish if it failed + // and then immediately return (or keep going, if requested by the build + // config). + let mut errors = ErrorsDuringDrain { count: 0 }; + // CAUTION! Do not use `?` or break out of the loop early. Every error + // must be handled in such a way that the loop is still allowed to + // drain event messages. + loop { + if errors.count == 0 || build_runner.bcx.build_config.keep_going { + if let Err(e) = self.spawn_work_if_possible(build_runner, jobserver_helper, scope) { + self.handle_error(&mut build_runner.bcx.gctx.shell(), &mut errors, e); + } + } + + // If after all that we're not actually running anything then we're + // done! + if self.active.is_empty() { + break; + } + + // And finally, before we block waiting for the next event, drop any + // excess tokens we may have accidentally acquired. Due to how our + // jobserver interface is architected we may acquire a token that we + // don't actually use, and if this happens just relinquish it back + // to the jobserver itself. + for event in self.wait_for_events() { + if let Err(event_err) = self.handle_event(build_runner, plan, event) { + self.handle_error(&mut build_runner.bcx.gctx.shell(), &mut errors, event_err); + } + } + } + self.progress.clear(); + + let profile_name = build_runner.bcx.build_config.requested_profile; + // NOTE: this may be a bit inaccurate, since this may not display the + // profile for what was actually built. Profile overrides can change + // these settings, and in some cases different targets are built with + // different profiles. To be accurate, it would need to collect a + // list of Units built, and maybe display a list of the different + // profiles used. However, to keep it simple and compatible with old + // behavior, we just display what the base profile is. + let profile = build_runner.bcx.profiles.base_profile(); + let mut opt_type = String::from(if profile.opt_level.as_str() == "0" { + "unoptimized" + } else { + "optimized" + }); + if profile.debuginfo.is_turned_on() { + opt_type += " + debuginfo"; + } + + let time_elapsed = util::elapsed(build_runner.bcx.gctx.creation_time().elapsed()); + if let Err(e) = self.timings.finished(build_runner, &errors.to_error()) { + self.handle_error(&mut build_runner.bcx.gctx.shell(), &mut errors, e); + } + if build_runner.bcx.build_config.emit_json() { + let mut shell = build_runner.bcx.gctx.shell(); + let msg = machine_message::BuildFinished { + success: errors.count == 0, + } + .to_json_string(); + if let Err(e) = writeln!(shell.out(), "{}", msg) { + self.handle_error(&mut shell, &mut errors, e); + } + } + + if let Some(error) = errors.to_error() { + // Any errors up to this point have already been printed via the + // `display_error` inside `handle_error`. + Some(anyhow::Error::new(AlreadyPrintedError::new(error))) + } else if self.queue.is_empty() && self.pending_queue.is_empty() { + let profile_link = build_runner.bcx.gctx.shell().err_hyperlink( + "https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles", + ); + let message = format!( + "{profile_link}`{profile_name}` profile [{opt_type}]{profile_link:#} target(s) in {time_elapsed}", + ); + if !build_runner.bcx.build_config.build_plan { + // It doesn't really matter if this fails. + let _ = build_runner.bcx.gctx.shell().status("Finished", message); + future_incompat::save_and_display_report( + build_runner.bcx, + &self.per_package_future_incompat_reports, + ); + } + + None + } else { + debug!("queue: {:#?}", self.queue); + Some(internal("finished with jobs still left in the queue")) + } + } + + fn handle_error( + &self, + shell: &mut Shell, + err_state: &mut ErrorsDuringDrain, + new_err: impl Into, + ) { + let new_err = new_err.into(); + if new_err.print_always || err_state.count == 0 { + crate::display_error(&new_err.error, shell); + if err_state.count == 0 && !self.active.is_empty() { + let _ = shell.warn("build failed, waiting for other jobs to finish..."); + } + err_state.count += 1; + } else { + tracing::warn!("{:?}", new_err.error); + } + } + + // This also records CPU usage and marks concurrency; we roughly want to do + // this as often as we spin on the events receiver (at least every 500ms or + // so). + fn tick_progress(&mut self) { + // Record some timing information if `--timings` is enabled, and + // this'll end up being a noop if we're not recording this + // information. + self.timings.mark_concurrency( + self.active.len(), + self.pending_queue.len(), + self.queue.len(), + ); + self.timings.record_cpu(); + + let active_names = self + .active + .values() + .map(|u| self.name_for_progress(u)) + .collect::>(); + let _ = self.progress.tick_now( + self.finished, + self.total_units, + &format!(": {}", active_names.join(", ")), + ); + } + + fn name_for_progress(&self, unit: &Unit) -> String { + let pkg_name = unit.pkg.name(); + let target_name = unit.target.name(); + match unit.mode { + CompileMode::Doc { .. } => format!("{}(doc)", pkg_name), + CompileMode::RunCustomBuild => format!("{}(build)", pkg_name), + CompileMode::Test | CompileMode::Check { test: true } => match unit.target.kind() { + TargetKind::Lib(_) => format!("{}(test)", target_name), + TargetKind::CustomBuild => panic!("cannot test build script"), + TargetKind::Bin => format!("{}(bin test)", target_name), + TargetKind::Test => format!("{}(test)", target_name), + TargetKind::Bench => format!("{}(bench)", target_name), + TargetKind::ExampleBin | TargetKind::ExampleLib(_) => { + format!("{}(example test)", target_name) + } + }, + _ => match unit.target.kind() { + TargetKind::Lib(_) => pkg_name.to_string(), + TargetKind::CustomBuild => format!("{}(build.rs)", pkg_name), + TargetKind::Bin => format!("{}(bin)", target_name), + TargetKind::Test => format!("{}(test)", target_name), + TargetKind::Bench => format!("{}(bench)", target_name), + TargetKind::ExampleBin | TargetKind::ExampleLib(_) => { + format!("{}(example)", target_name) + } + }, + } + } + + /// Executes a job. + /// + /// Fresh jobs block until finished (which should be very fast!), Dirty + /// jobs will spawn a thread in the background and return immediately. + fn run<'s>( + &mut self, + unit: &Unit, + job: Job, + build_runner: &BuildRunner<'_, '_>, + scope: &'s Scope<'s, '_>, + ) { + let id = JobId(self.next_id); + self.next_id = self.next_id.checked_add(1).unwrap(); + + debug!("start {}: {:?}", id, unit); + + assert!(self.active.insert(id, unit.clone()).is_none()); + + let messages = self.messages.clone(); + let is_fresh = job.freshness().is_fresh(); + let rmeta_required = build_runner.rmeta_required(unit); + + let doit = move |diag_dedupe| { + let state = JobState::new(id, messages, diag_dedupe, rmeta_required); + state.run_to_finish(job); + }; + + match is_fresh { + true => { + self.timings.add_fresh(); + // Running a fresh job on the same thread is often much faster than spawning a new + // thread to run the job. + doit(Some(&self.diag_dedupe)); + } + false => { + self.timings.add_dirty(); + scope.spawn(move || doit(None)); + } + } + } + + fn emit_log_messages( + &self, + unit: &Unit, + build_runner: &mut BuildRunner<'_, '_>, + show_warnings: bool, + ) -> CargoResult<()> { + let outputs = build_runner.build_script_outputs.lock().unwrap(); + let Some(metadata) = build_runner.find_build_script_metadata(unit) else { + return Ok(()); + }; + let bcx = &mut build_runner.bcx; + if let Some(output) = outputs.get(metadata) { + if !output.log_messages.is_empty() + && (show_warnings + || output + .log_messages + .iter() + .any(|(severity, _)| *severity == Severity::Error)) + { + let msg_with_package = + |msg: &str| format!("{}@{}: {}", unit.pkg.name(), unit.pkg.version(), msg); + + for (severity, message) in output.log_messages.iter() { + match severity { + Severity::Error => { + bcx.gctx.shell().error(msg_with_package(message))?; + } + Severity::Warning => { + bcx.gctx.shell().warn(msg_with_package(message))?; + } + } + } + } + } + + Ok(()) + } + + fn bump_warning_count(&mut self, id: JobId, emitted: bool, fixable: bool) { + let cnts = self.warning_count.entry(id).or_default(); + cnts.total += 1; + if !emitted { + cnts.duplicates += 1; + // Don't add to fixable if it's already been emitted + } else if fixable { + // Do not add anything to the fixable warning count if + // is `NotAllowed` since that indicates there was an + // error while building this `Unit` + if cnts.fixable_allowed() { + cnts.fixable = match cnts.fixable { + FixableWarnings::NotAllowed => FixableWarnings::NotAllowed, + FixableWarnings::Zero => FixableWarnings::Positive(1), + FixableWarnings::Positive(fixable) => FixableWarnings::Positive(fixable + 1), + }; + } + } + } + + /// Displays a final report of the warnings emitted by a particular job. + fn report_warning_count( + &mut self, + runner: &mut BuildRunner<'_, '_>, + id: JobId, + rustc_workspace_wrapper: &Option, + ) { + let gctx = runner.bcx.gctx; + let count = match self.warning_count.get(&id) { + // An error could add an entry for a `Unit` + // with 0 warnings but having fixable + // warnings be disallowed + Some(count) if count.total > 0 => count, + None | Some(_) => return, + }; + runner.compilation.warning_count += count.total; + let unit = &self.active[&id]; + let mut message = descriptive_pkg_name(&unit.pkg.name(), &unit.target, &unit.mode); + message.push_str(" generated "); + match count.total { + 1 => message.push_str("1 warning"), + n => { + let _ = write!(message, "{} warnings", n); + } + }; + match count.duplicates { + 0 => {} + 1 => message.push_str(" (1 duplicate)"), + n => { + let _ = write!(message, " ({} duplicates)", n); + } + } + // Only show the `cargo fix` message if its a local `Unit` + if unit.is_local() { + // Do not show this if there are any errors or no fixable warnings + if let FixableWarnings::Positive(fixable) = count.fixable { + // `cargo fix` doesn't have an option for custom builds + if !unit.target.is_custom_build() { + // To make sure the correct command is shown for `clippy` we + // check if `RUSTC_WORKSPACE_WRAPPER` is set and pointing towards + // `clippy-driver`. + let clippy = std::ffi::OsStr::new("clippy-driver"); + let command = match rustc_workspace_wrapper.as_ref().and_then(|x| x.file_stem()) + { + Some(wrapper) if wrapper == clippy => "cargo clippy --fix", + _ => "cargo fix", + }; + let mut args = { + let named = unit.target.description_named(); + // if its a lib we need to add the package to fix + if unit.target.is_lib() { + format!("{} -p {}", named, unit.pkg.name()) + } else { + named + } + }; + if unit.mode.is_rustc_test() + && !(unit.target.is_test() || unit.target.is_bench()) + { + args.push_str(" --tests"); + } + let mut suggestions = format!("{} suggestion", fixable); + if fixable > 1 { + suggestions.push_str("s") + } + let _ = write!( + message, + " (run `{command} --{args}` to apply {suggestions})" + ); + } + } + } + // Errors are ignored here because it is tricky to handle them + // correctly, and they aren't important. + let _ = gctx.shell().warn(message); + } + + fn finish( + &mut self, + id: JobId, + unit: &Unit, + artifact: Artifact, + build_runner: &mut BuildRunner<'_, '_>, + ) -> CargoResult<()> { + if unit.mode.is_run_custom_build() { + self.emit_log_messages( + unit, + build_runner, + unit.show_warnings(build_runner.bcx.gctx), + )?; + } + let unlocked = self.queue.finish(unit, &artifact); + match artifact { + Artifact::All => self.timings.unit_finished(id, unlocked), + Artifact::Metadata => self.timings.unit_rmeta_finished(id, unlocked), + } + Ok(()) + } + + // This isn't super trivial because we don't want to print loads and + // loads of information to the console, but we also want to produce a + // faithful representation of what's happening. This is somewhat nuanced + // as a package can start compiling *very* early on because of custom + // build commands and such. + // + // In general, we try to print "Compiling" for the first nontrivial task + // run for a package, regardless of when that is. We then don't print + // out any more information for a package after we've printed it once. + fn note_working_on( + &mut self, + gctx: &GlobalContext, + ws_root: &Path, + unit: &Unit, + fresh: &Freshness, + ) -> CargoResult<()> { + if (self.compiled.contains(&unit.pkg.package_id()) + && !unit.mode.is_doc() + && !unit.mode.is_doc_scrape()) + || (self.documented.contains(&unit.pkg.package_id()) && unit.mode.is_doc()) + || (self.scraped.contains(&unit.pkg.package_id()) && unit.mode.is_doc_scrape()) + { + return Ok(()); + } + + match fresh { + // Any dirty stage which runs at least one command gets printed as + // being a compiled package. + Dirty(dirty_reason) => { + if !dirty_reason.is_fresh_build() { + gctx.shell() + .verbose(|shell| dirty_reason.present_to(shell, unit, ws_root))?; + } + + if unit.mode.is_doc() { + self.documented.insert(unit.pkg.package_id()); + gctx.shell().status("Documenting", &unit.pkg)?; + } else if unit.mode.is_doc_test() { + // Skip doc test. + } else if unit.mode.is_doc_scrape() { + self.scraped.insert(unit.pkg.package_id()); + gctx.shell().status("Scraping", &unit.pkg)?; + } else { + self.compiled.insert(unit.pkg.package_id()); + if unit.mode.is_check() { + gctx.shell().status("Checking", &unit.pkg)?; + } else { + gctx.shell().status("Compiling", &unit.pkg)?; + } + } + } + Fresh => { + // If doc test are last, only print "Fresh" if nothing has been printed. + if self.counts[&unit.pkg.package_id()] == 0 + && !(unit.mode.is_doc_test() && self.compiled.contains(&unit.pkg.package_id())) + { + self.compiled.insert(unit.pkg.package_id()); + gctx.shell().verbose(|c| c.status("Fresh", &unit.pkg))?; + } + } + } + Ok(()) + } + + fn back_compat_notice( + &self, + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + ) -> CargoResult<()> { + if unit.pkg.name() != "diesel" + || unit.pkg.version() >= &Version::new(1, 4, 8) + || build_runner.bcx.ws.resolve_behavior() == ResolveBehavior::V1 + || !unit.pkg.package_id().source_id().is_registry() + || !unit.features.is_empty() + { + return Ok(()); + } + if !build_runner + .bcx + .unit_graph + .keys() + .any(|unit| unit.pkg.name() == "diesel" && !unit.features.is_empty()) + { + return Ok(()); + } + build_runner.bcx.gctx.shell().note( + "\ +This error may be due to an interaction between diesel and Cargo's new +feature resolver. Try updating to diesel 1.4.8 to fix this error. +", + )?; + Ok(()) + } +} + +impl ErrorsDuringDrain { + fn to_error(&self) -> Option { + match self.count { + 0 => None, + 1 => Some(format_err!("1 job failed")), + n => Some(format_err!("{} jobs failed", n)), + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/layout.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/layout.rs new file mode 100644 index 000000000..30062164d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/layout.rs @@ -0,0 +1,242 @@ +//! Management of the directory layout of a build +//! +//! The directory layout is a little tricky at times, hence a separate file to +//! house this logic. The current layout looks like this: +//! +//! ```text +//! # This is the root directory for all output, the top-level package +//! # places all of its output here. +//! target/ +//! +//! # Cache of `rustc -Vv` output for performance. +//! .rustc-info.json +//! +//! # All final artifacts are linked into this directory from `deps`. +//! # Note that named profiles will soon be included as separate directories +//! # here. They have a restricted format, similar to Rust identifiers, so +//! # Cargo-specific directories added in the future should use some prefix +//! # like `.` to avoid name collisions. +//! debug/ # or release/ +//! +//! # File used to lock the directory to prevent multiple cargo processes +//! # from using it at the same time. +//! .cargo-lock +//! +//! # Hidden directory that holds all of the fingerprint files for all +//! # packages +//! .fingerprint/ +//! # Each package is in a separate directory. +//! # Note that different target kinds have different filename prefixes. +//! $pkgname-$META/ +//! # Set of source filenames for this package. +//! dep-lib-$targetname +//! # Timestamp when this package was last built. +//! invoked.timestamp +//! # The fingerprint hash. +//! lib-$targetname +//! # Detailed information used for logging the reason why +//! # something is being recompiled. +//! lib-$targetname.json +//! # The console output from the compiler. This is cached +//! # so that warnings can be redisplayed for "fresh" units. +//! output-lib-$targetname +//! +//! # This is the root directory for all rustc artifacts except build +//! # scripts, examples, and test and bench executables. Almost every +//! # artifact should have a metadata hash added to its filename to +//! # prevent collisions. One notable exception is dynamic libraries. +//! deps/ +//! +//! # Each artifact dependency gets in its own directory. +//! /artifact/$pkgname-$META/$kind +//! +//! # Root directory for all compiled examples. +//! examples/ +//! +//! # Directory used to store incremental data for the compiler (when +//! # incremental is enabled. +//! incremental/ +//! +//! # This is the location at which the output of all custom build +//! # commands are rooted. +//! build/ +//! +//! # Each package gets its own directory where its build script and +//! # script output are placed +//! $pkgname-$META/ # For the build script itself. +//! # The build script executable (name may be changed by user). +//! build-script-build-$META +//! # Hard link to build-script-build-$META. +//! build-script-build +//! # Dependency information generated by rustc. +//! build-script-build-$META.d +//! # Debug information, depending on platform and profile +//! # settings. +//! +//! +//! # The package shows up twice with two different metadata hashes. +//! $pkgname-$META/ # For the output of the build script. +//! # Timestamp when the build script was last executed. +//! invoked.timestamp +//! # Directory where script can output files ($OUT_DIR). +//! out/ +//! # Output from the build script. +//! output +//! # Path to `out`, used to help when the target directory is +//! # moved. +//! root-output +//! # Stderr output from the build script. +//! stderr +//! +//! # Output from rustdoc +//! doc/ +//! +//! # Used by `cargo package` and `cargo publish` to build a `.crate` file. +//! package/ +//! +//! # Experimental feature for generated build scripts. +//! .metabuild/ +//! ``` +//! +//! When cross-compiling, the layout is the same, except it appears in +//! `target/$TRIPLE`. + +use crate::core::compiler::CompileTarget; +use crate::core::Workspace; +use crate::util::{CargoResult, FileLock}; +use cargo_util::paths; +use std::path::{Path, PathBuf}; + +/// Contains the paths of all target output locations. +/// +/// See module docs for more information. +pub struct Layout { + /// The root directory: `/path/to/target`. + /// If cross compiling: `/path/to/target/$TRIPLE`. + root: PathBuf, + /// The final artifact destination: `$root/debug` (or `release`). + dest: PathBuf, + /// The directory with rustc artifacts: `$dest/deps` + deps: PathBuf, + /// The directory for build scripts: `$dest/build` + build: PathBuf, + /// The directory for artifacts, i.e. binaries, cdylibs, staticlibs: `$dest/deps/artifact` + artifact: PathBuf, + /// The directory for incremental files: `$dest/incremental` + incremental: PathBuf, + /// The directory for fingerprints: `$dest/.fingerprint` + fingerprint: PathBuf, + /// The directory for examples: `$dest/examples` + examples: PathBuf, + /// The directory for rustdoc output: `$root/doc` + doc: PathBuf, + /// The directory for temporary data of integration tests and benches: `$dest/tmp` + tmp: PathBuf, + /// The lockfile for a build (`.cargo-lock`). Will be unlocked when this + /// struct is `drop`ped. + _lock: FileLock, +} + +impl Layout { + /// Calculate the paths for build output, lock the build directory, and return as a Layout. + /// + /// This function will block if the directory is already locked. + /// + /// `dest` should be the final artifact directory name. Currently either + /// "debug" or "release". + pub fn new( + ws: &Workspace<'_>, + target: Option, + dest: &str, + ) -> CargoResult { + let mut root = ws.target_dir(); + if let Some(target) = target { + root.push(target.short_name()); + } + let dest = root.join(dest); + // If the root directory doesn't already exist go ahead and create it + // here. Use this opportunity to exclude it from backups as well if the + // system supports it since this is a freshly created folder. + // + paths::create_dir_all_excluded_from_backups_atomic(root.as_path_unlocked())?; + // Now that the excluded from backups target root is created we can create the + // actual destination (sub)subdirectory. + paths::create_dir_all(dest.as_path_unlocked())?; + + // For now we don't do any more finer-grained locking on the artifact + // directory, so just lock the entire thing for the duration of this + // compile. + let lock = dest.open_rw_exclusive_create(".cargo-lock", ws.gctx(), "build directory")?; + let root = root.into_path_unlocked(); + let dest = dest.into_path_unlocked(); + let deps = dest.join("deps"); + let artifact = deps.join("artifact"); + + Ok(Layout { + deps, + build: dest.join("build"), + artifact, + incremental: dest.join("incremental"), + fingerprint: dest.join(".fingerprint"), + examples: dest.join("examples"), + doc: root.join("doc"), + tmp: root.join("tmp"), + root, + dest, + _lock: lock, + }) + } + + /// Makes sure all directories stored in the Layout exist on the filesystem. + pub fn prepare(&mut self) -> CargoResult<()> { + paths::create_dir_all(&self.deps)?; + paths::create_dir_all(&self.incremental)?; + paths::create_dir_all(&self.fingerprint)?; + paths::create_dir_all(&self.examples)?; + paths::create_dir_all(&self.build)?; + + Ok(()) + } + + /// Fetch the destination path for final artifacts (`/…/target/debug`). + pub fn dest(&self) -> &Path { + &self.dest + } + /// Fetch the deps path. + pub fn deps(&self) -> &Path { + &self.deps + } + /// Fetch the examples path. + pub fn examples(&self) -> &Path { + &self.examples + } + /// Fetch the doc path. + pub fn doc(&self) -> &Path { + &self.doc + } + /// Fetch the root path (`/…/target`). + pub fn root(&self) -> &Path { + &self.root + } + /// Fetch the incremental path. + pub fn incremental(&self) -> &Path { + &self.incremental + } + /// Fetch the fingerprint path. + pub fn fingerprint(&self) -> &Path { + &self.fingerprint + } + /// Fetch the build script path. + pub fn build(&self) -> &Path { + &self.build + } + /// Fetch the artifact path. + pub fn artifact(&self) -> &Path { + &self.artifact + } + /// Create and return the tmp path. + pub fn prepare_tmp(&self) -> CargoResult<&Path> { + paths::create_dir_all(&self.tmp)?; + Ok(&self.tmp) + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/links.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/links.rs new file mode 100644 index 000000000..cfbf92ef0 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/links.rs @@ -0,0 +1,60 @@ +use super::unit_graph::UnitGraph; +use crate::core::resolver::errors::describe_path; +use crate::core::{PackageId, Resolve}; +use crate::util::errors::CargoResult; +use std::collections::{HashMap, HashSet}; + +/// Validates [`package.links`] field in the manifest file does not conflict +/// between packages. +/// +/// NOTE: This is the *old* links validator. Links are usually validated in the +/// resolver. However, the `links` field was added to the index in early 2018 +/// (see [rust-lang/cargo#4978]). However, `links` has been around since 2014, +/// so there are still many crates in the index that don't have `links` +/// properly set in the index (over 600 at the time of this writing in 2019). +/// This can probably be removed at some point in the future, though it might +/// be worth considering fixing the index. +/// +/// [rust-lang/cargo#4978]: https://github.com/rust-lang/cargo/pull/4978 +/// [`package.links`]: https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#the-links-manifest-key +pub fn validate_links(resolve: &Resolve, unit_graph: &UnitGraph) -> CargoResult<()> { + let mut validated: HashSet = HashSet::new(); + let mut links: HashMap = HashMap::new(); + let mut units: Vec<_> = unit_graph.keys().collect(); + // Sort primarily to make testing easier. + units.sort_unstable(); + for unit in units { + if !validated.insert(unit.pkg.package_id()) { + continue; + } + let Some(lib) = unit.pkg.manifest().links() else { + continue; + }; + if let Some(&prev) = links.get(lib) { + let prev_path = resolve + .path_to_top(&prev) + .into_iter() + .map(|(p, d)| (p, d.and_then(|d| d.iter().next()))); + let pkg = unit.pkg.package_id(); + let path = resolve + .path_to_top(&pkg) + .into_iter() + .map(|(p, d)| (p, d.and_then(|d| d.iter().next()))); + anyhow::bail!( + "multiple packages link to native library `{}`, \ + but a native library can be linked only once\n\ + \n\ + {}\nlinks to native library `{}`\n\ + \n\ + {}\nalso links to native library `{}`", + lib, + describe_path(prev_path), + lib, + describe_path(path), + lib + ) + } + links.insert(lib.to_string(), unit.pkg.package_id()); + } + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/lto.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/lto.rs new file mode 100644 index 000000000..e934244c9 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/lto.rs @@ -0,0 +1,194 @@ +use crate::core::compiler::{BuildContext, CompileMode, CrateType, Unit}; +use crate::core::profiles; +use crate::util::interning::InternedString; + +use crate::util::errors::CargoResult; +use std::collections::hash_map::{Entry, HashMap}; + +/// Possible ways to run rustc and request various parts of [LTO]. +/// +/// Variant | Flag | Object Code | Bitcode +/// -------------------|------------------------|-------------|-------- +/// `Run` | `-C lto=foo` | n/a | n/a +/// `Off` | `-C lto=off` | n/a | n/a +/// `OnlyBitcode` | `-C linker-plugin-lto` | | ✓ +/// `ObjectAndBitcode` | | ✓ | ✓ +/// `OnlyObject` | `-C embed-bitcode=no` | ✓ | +/// +/// [LTO]: https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#lto +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum Lto { + /// LTO is run for this rustc, and it's `-Clto=foo`. If the given value is + /// None, that corresponds to `-Clto` with no argument, which means do + /// "fat" LTO. + Run(Option), + + /// LTO has been explicitly listed as "off". This means no thin-local-LTO, + /// no LTO anywhere, I really mean it! + Off, + + /// This rustc invocation only needs to produce bitcode (it is *only* used + /// for LTO), there's no need to produce object files, so we can pass + /// `-Clinker-plugin-lto` + OnlyBitcode, + + /// This rustc invocation needs to embed bitcode in object files. This means + /// that object files may be used for a normal link, and the crate may be + /// loaded for LTO later, so both are required. + ObjectAndBitcode, + + /// This should not include bitcode. This is primarily to reduce disk + /// space usage. + OnlyObject, +} + +pub fn generate(bcx: &BuildContext<'_, '_>) -> CargoResult> { + let mut map = HashMap::new(); + for unit in bcx.roots.iter() { + let root_lto = match unit.profile.lto { + // LTO not requested, no need for bitcode. + profiles::Lto::Bool(false) => Lto::OnlyObject, + profiles::Lto::Off => Lto::Off, + _ => { + let crate_types = unit.target.rustc_crate_types(); + if unit.target.for_host() { + Lto::OnlyObject + } else if needs_object(&crate_types) { + lto_when_needs_object(&crate_types) + } else { + // This may or may not participate in LTO, let's start + // with the minimum requirements. This may be expanded in + // `calculate` below if necessary. + Lto::OnlyBitcode + } + } + }; + calculate(bcx, &mut map, unit, root_lto)?; + } + Ok(map) +} + +/// Whether or not any of these crate types need object code. +fn needs_object(crate_types: &[CrateType]) -> bool { + crate_types.iter().any(|k| k.can_lto() || k.is_dynamic()) +} + +/// Lto setting to use when this unit needs object code. +fn lto_when_needs_object(crate_types: &[CrateType]) -> Lto { + if crate_types.iter().all(|ct| *ct == CrateType::Dylib) { + // A dylib whose parent is running LTO. rustc currently + // doesn't support LTO with dylibs, so bitcode is not + // needed. + Lto::OnlyObject + } else { + // Mixed rlib with a dylib or cdylib whose parent is running LTO. This + // needs both: bitcode for the rlib (for LTO) and object code for the + // dylib. + Lto::ObjectAndBitcode + } +} + +fn calculate( + bcx: &BuildContext<'_, '_>, + map: &mut HashMap, + unit: &Unit, + parent_lto: Lto, +) -> CargoResult<()> { + let crate_types = match unit.mode { + // Note: Doctest ignores LTO, but for now we'll compute it as-if it is + // a Bin, in case it is ever supported in the future. + CompileMode::Test | CompileMode::Bench | CompileMode::Doctest => vec![CrateType::Bin], + // Notes on other modes: + // - Check: Treat as the underlying type, it doesn't really matter. + // - Doc: LTO is N/A for the Doc unit itself since rustdoc does not + // support codegen flags. We still compute the dependencies, which + // are mostly `Check`. + // - RunCustomBuild is ignored because it is always "for_host". + _ => unit.target.rustc_crate_types(), + }; + // LTO can only be performed if *all* of the crate types support it. + // For example, a cdylib/rlib combination won't allow LTO. + let all_lto_types = crate_types.iter().all(CrateType::can_lto); + // Compute the LTO based on the profile, and what our parent requires. + let lto = if unit.target.for_host() { + // Disable LTO for host builds since we only really want to perform LTO + // for the final binary, and LTO on plugins/build scripts/proc macros is + // largely not desired. + Lto::OnlyObject + } else if all_lto_types { + // Note that this ignores the `parent_lto` because this isn't a + // linkable crate type; this unit is not being embedded in the parent. + match unit.profile.lto { + profiles::Lto::Named(s) => Lto::Run(Some(s)), + profiles::Lto::Off => Lto::Off, + profiles::Lto::Bool(true) => Lto::Run(None), + profiles::Lto::Bool(false) => Lto::OnlyObject, + } + } else { + match (parent_lto, needs_object(&crate_types)) { + // An rlib whose parent is running LTO, we only need bitcode. + (Lto::Run(_), false) => Lto::OnlyBitcode, + // LTO when something needs object code. + (Lto::Run(_), true) | (Lto::OnlyBitcode, true) => lto_when_needs_object(&crate_types), + // LTO is disabled, continue to disable it. + (Lto::Off, _) => Lto::Off, + // If this doesn't have any requirements, or the requirements are + // already satisfied, then stay with our parent. + (_, false) | (Lto::OnlyObject, true) | (Lto::ObjectAndBitcode, true) => parent_lto, + } + }; + + // Merge the computed LTO. If this unit appears multiple times in the + // graph, the merge may expand the requirements. + let merged_lto = match map.entry(unit.clone()) { + // If we haven't seen this unit before then insert our value and keep + // going. + Entry::Vacant(v) => *v.insert(lto), + + Entry::Occupied(mut v) => { + let result = match (lto, v.get()) { + // No change in requirements. + (Lto::OnlyBitcode, Lto::OnlyBitcode) => Lto::OnlyBitcode, + (Lto::OnlyObject, Lto::OnlyObject) => Lto::OnlyObject, + + // Once we're running LTO we keep running LTO. We should always + // calculate the same thing here each iteration because if we + // see this twice then it means, for example, two unit tests + // depend on a binary, which is normal. + (Lto::Run(s), _) | (_, &Lto::Run(s)) => Lto::Run(s), + + // Off means off! This has the same reasoning as `Lto::Run`. + (Lto::Off, _) | (_, Lto::Off) => Lto::Off, + + // Once a target has requested both, that's the maximal amount + // of work that can be done, so we just keep doing that work. + (Lto::ObjectAndBitcode, _) | (_, Lto::ObjectAndBitcode) => Lto::ObjectAndBitcode, + + // Upgrade so that both requirements can be met. + // + // This is where the trickiness happens. This unit needs + // bitcode and the previously calculated value for this unit + // says it didn't need bitcode (or vice versa). This means that + // we're a shared dependency between some targets which require + // LTO and some which don't. This means that instead of being + // either only-objects or only-bitcode we have to embed both in + // rlibs (used for different compilations), so we switch to + // including both. + (Lto::OnlyObject, Lto::OnlyBitcode) | (Lto::OnlyBitcode, Lto::OnlyObject) => { + Lto::ObjectAndBitcode + } + }; + // No need to recurse if we calculated the same value as before. + if result == *v.get() { + return Ok(()); + } + v.insert(result); + result + } + }; + + for dep in &bcx.unit_graph[unit] { + calculate(bcx, map, &dep.unit, merged_lto)?; + } + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/mod.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/mod.rs new file mode 100644 index 000000000..277039685 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/mod.rs @@ -0,0 +1,1997 @@ +//! # Interact with the compiler +//! +//! If you consider [`ops::cargo_compile::compile`] as a `rustc` driver but on +//! Cargo side, this module is kinda the `rustc_interface` for that merits. +//! It contains all the interaction between Cargo and the rustc compiler, +//! from preparing the context for the entire build process, to scheduling +//! and executing each unit of work (e.g. running `rustc`), to managing and +//! caching the output artifact of a build. +//! +//! However, it hasn't yet exposed a clear definition of each phase or session, +//! 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 containing all information you need +//! before a build gets started. +//! * [`BuildRunner`] is the center of the world, coordinating a running build and +//! collecting information from it. +//! * [`custom_build`] is the home of build script executions and output parsing. +//! * [`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 +//! 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. +//! * [`Unit`] contains sufficient information to build something, usually +//! turning into a compiler invocation in a later phase. +//! +//! [^1]: Maybe [`-Zbuild-plan`](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-plan) +//! was designed to serve that purpose but still [in flux](https://github.com/rust-lang/cargo/issues/7614). +//! +//! [`ops::cargo_compile::compile`]: crate::ops::compile + +pub mod artifact; +mod build_config; +pub(crate) mod build_context; +mod build_plan; +pub(crate) mod build_runner; +mod compilation; +mod compile_kind; +mod crate_type; +mod custom_build; +pub(crate) mod fingerprint; +pub mod future_incompat; +pub(crate) mod job_queue; +pub(crate) mod layout; +mod links; +mod lto; +mod output_depinfo; +pub mod rustdoc; +pub mod standard_lib; +mod timings; +mod unit; +pub mod unit_dependencies; +pub mod unit_graph; + +use std::borrow::Cow; +use std::collections::{HashMap, HashSet}; +use std::env; +use std::ffi::{OsStr, OsString}; +use std::fmt::Display; +use std::fs::{self, File}; +use std::io::{BufRead, Write}; +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use anyhow::{Context as _, Error}; +use lazycell::LazyCell; +use tracing::{debug, trace}; + +pub use self::build_config::{BuildConfig, CompileMode, MessageFormat, TimingOutput}; +pub use self::build_context::{ + BuildContext, FileFlavor, FileType, RustDocFingerprint, RustcTargetData, TargetInfo, +}; +use self::build_plan::BuildPlan; +pub use self::build_runner::{BuildRunner, Metadata, UnitHash}; +pub use self::compilation::{Compilation, Doctest, UnitOutput}; +pub use self::compile_kind::{CompileKind, CompileTarget}; +pub use self::crate_type::CrateType; +pub use self::custom_build::LinkArgTarget; +pub use self::custom_build::{BuildOutput, BuildScriptOutputs, BuildScripts}; +pub(crate) use self::fingerprint::DirtyReason; +pub use self::job_queue::Freshness; +use self::job_queue::{Job, JobQueue, JobState, Work}; +pub(crate) use self::layout::Layout; +pub use self::lto::Lto; +use self::output_depinfo::output_depinfo; +use self::unit_graph::UnitDep; +use crate::core::compiler::future_incompat::FutureIncompatReport; +pub use crate::core::compiler::unit::{Unit, UnitInterner}; +use crate::core::manifest::TargetSourcePath; +use crate::core::profiles::{PanicStrategy, Profile, StripInner}; +use crate::core::{Feature, PackageId, Target, Verbosity}; +use crate::util::context::WarningHandling; +use crate::util::errors::{CargoResult, VerboseError}; +use crate::util::interning::InternedString; +use crate::util::machine_message::{self, Message}; +use crate::util::{add_path_args, internal}; +use cargo_util::{paths, ProcessBuilder, ProcessError}; +use cargo_util_schemas::manifest::TomlDebugInfo; +use cargo_util_schemas::manifest::TomlTrimPaths; +use cargo_util_schemas::manifest::TomlTrimPathsValue; +use rustfix::diagnostics::Applicability; + +const RUSTDOC_CRATE_VERSION_FLAG: &str = "--crate-version"; + +/// A glorified callback for executing calls to rustc. Rather than calling rustc +/// directly, we'll use an `Executor`, giving clients an opportunity to intercept +/// the build calls. +pub trait Executor: Send + Sync + 'static { + /// Called after a rustc process invocation is prepared up-front for a given + /// unit of work (may still be modified for runtime-known dependencies, when + /// the work is actually executed). + fn init(&self, _build_runner: &BuildRunner<'_, '_>, _unit: &Unit) {} + + /// In case of an `Err`, Cargo will not continue with the build process for + /// this package. + fn exec( + &self, + cmd: &ProcessBuilder, + id: PackageId, + target: &Target, + mode: CompileMode, + on_stdout_line: &mut dyn FnMut(&str) -> CargoResult<()>, + on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>, + ) -> CargoResult<()>; + + /// Queried when queuing each unit of work. If it returns true, then the + /// unit will always be rebuilt, independent of whether it needs to be. + fn force_rebuild(&self, _unit: &Unit) -> bool { + false + } +} + +/// A `DefaultExecutor` calls rustc without doing anything else. It is Cargo's +/// default behaviour. +#[derive(Copy, Clone)] +pub struct DefaultExecutor; + +impl Executor for DefaultExecutor { + fn exec( + &self, + cmd: &ProcessBuilder, + _id: PackageId, + _target: &Target, + _mode: CompileMode, + on_stdout_line: &mut dyn FnMut(&str) -> CargoResult<()>, + on_stderr_line: &mut dyn FnMut(&str) -> CargoResult<()>, + ) -> CargoResult<()> { + cmd.exec_with_streaming(on_stdout_line, on_stderr_line, false) + .map(drop) + } +} + +/// Builds up and enqueue a list of pending jobs onto the `job` queue. +/// +/// Starting from the `unit`, this function recursively calls itself to build +/// all jobs for dependencies of the `unit`. Each of these jobs represents +/// compiling a particular package. +/// +/// Note that **no actual work is executed as part of this**, that's all done +/// next as part of [`JobQueue::execute`] function which will run everything +/// in order with proper parallelism. +#[tracing::instrument(skip(build_runner, jobs, plan, exec))] +fn compile<'gctx>( + build_runner: &mut BuildRunner<'_, 'gctx>, + jobs: &mut JobQueue<'gctx>, + plan: &mut BuildPlan, + unit: &Unit, + exec: &Arc, + force_rebuild: bool, +) -> CargoResult<()> { + let bcx = build_runner.bcx; + let build_plan = bcx.build_config.build_plan; + if !build_runner.compiled.insert(unit.clone()) { + return Ok(()); + } + + // Build up the work to be done to compile this unit, enqueuing it once + // we've got everything constructed. + fingerprint::prepare_init(build_runner, unit)?; + + let job = if unit.mode.is_run_custom_build() { + custom_build::prepare(build_runner, unit)? + } else if unit.mode.is_doc_test() { + // We run these targets later, so this is just a no-op for now. + Job::new_fresh() + } else if build_plan { + Job::new_dirty( + rustc(build_runner, unit, &exec.clone())?, + DirtyReason::FreshBuild, + ) + } else { + let force = exec.force_rebuild(unit) || force_rebuild; + let mut job = fingerprint::prepare_target(build_runner, unit, force)?; + job.before(if job.freshness().is_dirty() { + let work = if unit.mode.is_doc() || unit.mode.is_doc_scrape() { + rustdoc(build_runner, unit)? + } else { + rustc(build_runner, unit, exec)? + }; + work.then(link_targets(build_runner, unit, false)?) + } else { + // We always replay the output cache, + // since it might contain future-incompat-report messages + let show_diagnostics = unit.show_warnings(bcx.gctx) + && build_runner.bcx.gctx.warning_handling()? != WarningHandling::Allow; + let work = replay_output_cache( + unit.pkg.package_id(), + PathBuf::from(unit.pkg.manifest_path()), + &unit.target, + build_runner.files().message_cache_path(unit), + build_runner.bcx.build_config.message_format, + show_diagnostics, + ); + // Need to link targets on both the dirty and fresh. + work.then(link_targets(build_runner, unit, true)?) + }); + + job + }; + jobs.enqueue(build_runner, unit, job)?; + + // Be sure to compile all dependencies of this target as well. + let deps = Vec::from(build_runner.unit_deps(unit)); // Create vec due to mutable borrow. + for dep in deps { + compile(build_runner, jobs, plan, &dep.unit, exec, false)?; + } + if build_plan { + plan.add(build_runner, unit)?; + } + + Ok(()) +} + +/// Generates the warning message used when fallible doc-scrape units fail, +/// either for rustdoc or rustc. +fn make_failed_scrape_diagnostic( + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + top_line: impl Display, +) -> String { + let manifest_path = unit.pkg.manifest_path(); + let relative_manifest_path = manifest_path + .strip_prefix(build_runner.bcx.ws.root()) + .unwrap_or(&manifest_path); + + format!( + "\ +{top_line} + Try running with `--verbose` to see the error message. + If an example should not be scanned, then consider adding `doc-scrape-examples = false` to its `[[example]]` definition in {}", + relative_manifest_path.display() + ) +} + +/// Creates a unit of work invoking `rustc` for building the `unit`. +fn rustc( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, + exec: &Arc, +) -> CargoResult { + let mut rustc = prepare_rustc(build_runner, unit)?; + let build_plan = build_runner.bcx.build_config.build_plan; + + let name = unit.pkg.name(); + let buildkey = unit.buildkey(); + + let outputs = build_runner.outputs(unit)?; + let root = build_runner.files().out_dir(unit); + + // Prepare the native lib state (extra `-L` and `-l` flags). + let build_script_outputs = Arc::clone(&build_runner.build_script_outputs); + let current_id = unit.pkg.package_id(); + let manifest_path = PathBuf::from(unit.pkg.manifest_path()); + let build_scripts = build_runner.build_scripts.get(unit).cloned(); + + // If we are a binary and the package also contains a library, then we + // don't pass the `-l` flags. + let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib()); + + let dep_info_name = + if let Some(c_extra_filename) = build_runner.files().metadata(unit).c_extra_filename() { + format!("{}-{}.d", unit.target.crate_name(), c_extra_filename) + } else { + format!("{}.d", unit.target.crate_name()) + }; + let rustc_dep_info_loc = root.join(dep_info_name); + let dep_info_loc = fingerprint::dep_info_loc(build_runner, unit); + + let mut output_options = OutputOptions::new(build_runner, unit); + let package_id = unit.pkg.package_id(); + let target = Target::clone(&unit.target); + let mode = unit.mode; + + exec.init(build_runner, unit); + let exec = exec.clone(); + + let root_output = build_runner.files().host_dest().to_path_buf(); + let target_dir = build_runner.bcx.ws.target_dir().into_path_unlocked(); + let pkg_root = unit.pkg.root().to_path_buf(); + let cwd = rustc + .get_cwd() + .unwrap_or_else(|| build_runner.bcx.gctx.cwd()) + .to_path_buf(); + let fingerprint_dir = build_runner.files().fingerprint_dir(unit); + let script_metadata = build_runner.find_build_script_metadata(unit); + let is_local = unit.is_local(); + let artifact = unit.artifact; + + let hide_diagnostics_for_scrape_unit = build_runner.bcx.unit_can_fail_for_docscraping(unit) + && !matches!( + build_runner.bcx.gctx.shell().verbosity(), + Verbosity::Verbose + ); + let failed_scrape_diagnostic = hide_diagnostics_for_scrape_unit.then(|| { + // If this unit is needed for doc-scraping, then we generate a diagnostic that + // describes the set of reverse-dependencies that cause the unit to be needed. + let target_desc = unit.target.description_named(); + let mut for_scrape_units = build_runner + .bcx + .scrape_units_have_dep_on(unit) + .into_iter() + .map(|unit| unit.target.description_named()) + .collect::>(); + for_scrape_units.sort(); + let for_scrape_units = for_scrape_units.join(", "); + make_failed_scrape_diagnostic(build_runner, unit, format_args!("failed to check {target_desc} in package `{name}` as a prerequisite for scraping examples from: {for_scrape_units}")) + }); + if hide_diagnostics_for_scrape_unit { + output_options.show_diagnostics = false; + } + let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?); + return Ok(Work::new(move |state| { + // Artifacts are in a different location than typical units, + // hence we must assure the crate- and target-dependent + // directory is present. + if artifact.is_true() { + paths::create_dir_all(&root)?; + } + + // Only at runtime have we discovered what the extra -L and -l + // arguments are for native libraries, so we process those here. We + // also need to be sure to add any -L paths for our plugins to the + // dynamic library load path as a plugin's dynamic library may be + // located somewhere in there. + // Finally, if custom environment variables have been produced by + // previous build scripts, we include them in the rustc invocation. + if let Some(build_scripts) = build_scripts { + let script_outputs = build_script_outputs.lock().unwrap(); + if !build_plan { + add_native_deps( + &mut rustc, + &script_outputs, + &build_scripts, + pass_l_flag, + &target, + current_id, + )?; + add_plugin_deps(&mut rustc, &script_outputs, &build_scripts, &root_output)?; + } + add_custom_flags(&mut rustc, &script_outputs, script_metadata)?; + } + + for output in outputs.iter() { + // If there is both an rmeta and rlib, rustc will prefer to use the + // rlib, even if it is older. Therefore, we must delete the rlib to + // force using the new rmeta. + if output.path.extension() == Some(OsStr::new("rmeta")) { + let dst = root.join(&output.path).with_extension("rlib"); + if dst.exists() { + paths::remove_file(&dst)?; + } + } + + // Some linkers do not remove the executable, but truncate and modify it. + // That results in the old hard-link being modified even after renamed. + // We delete the old artifact here to prevent this behavior from confusing users. + // See rust-lang/cargo#8348. + if output.hardlink.is_some() && output.path.exists() { + _ = paths::remove_file(&output.path).map_err(|e| { + tracing::debug!( + "failed to delete previous output file `{:?}`: {e:?}", + output.path + ); + }); + } + } + + state.running(&rustc); + let timestamp = paths::set_invocation_time(&fingerprint_dir)?; + if build_plan { + state.build_plan(buildkey, rustc.clone(), outputs.clone()); + } else { + let result = exec + .exec( + &rustc, + package_id, + &target, + mode, + &mut |line| on_stdout_line(state, line, package_id, &target), + &mut |line| { + on_stderr_line( + state, + line, + package_id, + &manifest_path, + &target, + &mut output_options, + ) + }, + ) + .map_err(|e| { + if output_options.errors_seen == 0 { + // If we didn't expect an error, do not require --verbose to fail. + // This is intended to debug + // https://github.com/rust-lang/crater/issues/733, where we are seeing + // Cargo exit unsuccessfully while seeming to not show any errors. + e + } else { + verbose_if_simple_exit_code(e) + } + }) + .with_context(|| { + // adapted from rustc_errors/src/lib.rs + let warnings = match output_options.warnings_seen { + 0 => String::new(), + 1 => "; 1 warning emitted".to_string(), + count => format!("; {} warnings emitted", count), + }; + let errors = match output_options.errors_seen { + 0 => String::new(), + 1 => " due to 1 previous error".to_string(), + count => format!(" due to {} previous errors", count), + }; + let name = descriptive_pkg_name(&name, &target, &mode); + format!("could not compile {name}{errors}{warnings}") + }); + + if let Err(e) = result { + if let Some(diagnostic) = failed_scrape_diagnostic { + state.warning(diagnostic)?; + } + + return Err(e); + } + + // Exec should never return with success *and* generate an error. + debug_assert_eq!(output_options.errors_seen, 0); + } + + if rustc_dep_info_loc.exists() { + fingerprint::translate_dep_info( + &rustc_dep_info_loc, + &dep_info_loc, + &cwd, + &pkg_root, + &target_dir, + &rustc, + // Do not track source files in the fingerprint for registry dependencies. + is_local, + &env_config, + ) + .with_context(|| { + internal(format!( + "could not parse/generate dep info at: {}", + rustc_dep_info_loc.display() + )) + })?; + // This mtime shift allows Cargo to detect if a source file was + // modified in the middle of the build. + paths::set_file_time_no_err(dep_info_loc, timestamp); + } + + Ok(()) + })); + + // Add all relevant `-L` and `-l` flags from dependencies (now calculated and + // present in `state`) to the command provided. + fn add_native_deps( + rustc: &mut ProcessBuilder, + build_script_outputs: &BuildScriptOutputs, + build_scripts: &BuildScripts, + pass_l_flag: bool, + target: &Target, + current_id: PackageId, + ) -> CargoResult<()> { + for key in build_scripts.to_link.iter() { + let output = build_script_outputs.get(key.1).ok_or_else(|| { + internal(format!( + "couldn't find build script output for {}/{}", + key.0, key.1 + )) + })?; + for path in output.library_paths.iter() { + rustc.arg("-L").arg(path); + } + + if key.0 == current_id { + if pass_l_flag { + for name in output.library_links.iter() { + rustc.arg("-l").arg(name); + } + } + } + + for (lt, arg) in &output.linker_args { + // There was an unintentional change where cdylibs were + // allowed to be passed via transitive dependencies. This + // clause should have been kept in the `if` block above. For + // now, continue allowing it for cdylib only. + // See https://github.com/rust-lang/cargo/issues/9562 + if lt.applies_to(target) && (key.0 == current_id || *lt == LinkArgTarget::Cdylib) { + rustc.arg("-C").arg(format!("link-arg={}", arg)); + } + } + } + Ok(()) + } +} + +fn verbose_if_simple_exit_code(err: Error) -> Error { + // If a signal on unix (`code == None`) or an abnormal termination + // on Windows (codes like `0xC0000409`), don't hide the error details. + match err + .downcast_ref::() + .as_ref() + .and_then(|perr| perr.code) + { + Some(n) if cargo_util::is_simple_exit_code(n) => VerboseError::new(err).into(), + _ => err, + } +} + +/// Link the compiled target (often of form `foo-{metadata_hash}`) to the +/// final target. This must happen during both "Fresh" and "Compile". +fn link_targets( + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, + fresh: bool, +) -> CargoResult { + let bcx = build_runner.bcx; + let outputs = build_runner.outputs(unit)?; + let export_dir = build_runner.files().export_dir(); + let package_id = unit.pkg.package_id(); + let manifest_path = PathBuf::from(unit.pkg.manifest_path()); + let profile = unit.profile.clone(); + let unit_mode = unit.mode; + let features = unit.features.iter().map(|s| s.to_string()).collect(); + let json_messages = bcx.build_config.emit_json(); + let executable = build_runner.get_executable(unit)?; + let mut target = Target::clone(&unit.target); + if let TargetSourcePath::Metabuild = target.src_path() { + // Give it something to serialize. + let path = unit + .pkg + .manifest() + .metabuild_path(build_runner.bcx.ws.target_dir()); + target.set_src_path(TargetSourcePath::Path(path)); + } + + Ok(Work::new(move |state| { + // If we're a "root crate", e.g., the target of this compilation, then we + // hard link our outputs out of the `deps` directory into the directory + // above. This means that `cargo build` will produce binaries in + // `target/debug` which one probably expects. + let mut destinations = vec![]; + for output in outputs.iter() { + let src = &output.path; + // This may have been a `cargo rustc` command which changes the + // output, so the source may not actually exist. + if !src.exists() { + continue; + } + let Some(dst) = output.hardlink.as_ref() else { + destinations.push(src.clone()); + continue; + }; + destinations.push(dst.clone()); + paths::link_or_copy(src, dst)?; + if let Some(ref path) = output.export_path { + let export_dir = export_dir.as_ref().unwrap(); + paths::create_dir_all(export_dir)?; + + paths::link_or_copy(src, path)?; + } + } + + if json_messages { + let debuginfo = match profile.debuginfo.into_inner() { + TomlDebugInfo::None => machine_message::ArtifactDebuginfo::Int(0), + TomlDebugInfo::Limited => machine_message::ArtifactDebuginfo::Int(1), + TomlDebugInfo::Full => machine_message::ArtifactDebuginfo::Int(2), + TomlDebugInfo::LineDirectivesOnly => { + machine_message::ArtifactDebuginfo::Named("line-directives-only") + } + TomlDebugInfo::LineTablesOnly => { + machine_message::ArtifactDebuginfo::Named("line-tables-only") + } + }; + let art_profile = machine_message::ArtifactProfile { + opt_level: profile.opt_level.as_str(), + debuginfo: Some(debuginfo), + debug_assertions: profile.debug_assertions, + overflow_checks: profile.overflow_checks, + test: unit_mode.is_any_test(), + }; + + let msg = machine_message::Artifact { + package_id: package_id.to_spec(), + manifest_path, + target: &target, + profile: art_profile, + features, + filenames: destinations, + executable, + fresh, + } + .to_json_string(); + state.stdout(msg)?; + } + Ok(()) + })) +} + +// For all plugin dependencies, add their -L paths (now calculated and present +// in `build_script_outputs`) to the dynamic library load path for the command +// to execute. +fn add_plugin_deps( + rustc: &mut ProcessBuilder, + build_script_outputs: &BuildScriptOutputs, + build_scripts: &BuildScripts, + root_output: &Path, +) -> CargoResult<()> { + let var = paths::dylib_path_envvar(); + let search_path = rustc.get_env(var).unwrap_or_default(); + let mut search_path = env::split_paths(&search_path).collect::>(); + for (pkg_id, metadata) in &build_scripts.plugins { + let output = build_script_outputs + .get(*metadata) + .ok_or_else(|| internal(format!("couldn't find libs for plugin dep {}", pkg_id)))?; + search_path.append(&mut filter_dynamic_search_path( + output.library_paths.iter(), + root_output, + )); + } + let search_path = paths::join_paths(&search_path, var)?; + rustc.env(var, &search_path); + Ok(()) +} + +// Determine paths to add to the dynamic search path from -L entries +// +// Strip off prefixes like "native=" or "framework=" and filter out directories +// **not** inside our output directory since they are likely spurious and can cause +// clashes with system shared libraries (issue #3366). +fn filter_dynamic_search_path<'a, I>(paths: I, root_output: &Path) -> Vec +where + I: Iterator, +{ + let mut search_path = vec![]; + for dir in paths { + 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); + } else { + debug!( + "Not including path {} in runtime library search path because it is \ + outside target root {}", + dir.display(), + root_output.display() + ); + } + } + search_path +} + +/// Prepares flags and environments we can compute for a `rustc` invocation +/// before the job queue starts compiling any unit. +/// +/// This builds a static view of the invocation. Flags depending on the +/// completion of other units will be added later in runtime, such as flags +/// from build scripts. +fn prepare_rustc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult { + let is_primary = build_runner.is_primary_package(unit); + let is_workspace = build_runner.bcx.ws.is_member(&unit.pkg); + + let mut base = build_runner + .compilation + .rustc_process(unit, is_primary, is_workspace)?; + build_base_args(build_runner, &mut base, unit)?; + + base.inherit_jobserver(&build_runner.jobserver); + build_deps_args(&mut base, build_runner, unit)?; + add_cap_lints(build_runner.bcx, unit, &mut base); + if let Some(args) = build_runner.bcx.extra_args_for(unit) { + base.args(args); + } + base.args(&unit.rustflags); + if build_runner.bcx.gctx.cli_unstable().binary_dep_depinfo { + base.arg("-Z").arg("binary-dep-depinfo"); + } + if build_runner.bcx.gctx.cli_unstable().checksum_freshness { + base.arg("-Z").arg("checksum-hash-algorithm=blake3"); + } + + if is_primary { + base.env("CARGO_PRIMARY_PACKAGE", "1"); + } + + if unit.target.is_test() || unit.target.is_bench() { + let tmp = build_runner.files().layout(unit.kind).prepare_tmp()?; + base.env("CARGO_TARGET_TMPDIR", tmp.display().to_string()); + } + + Ok(base) +} + +/// Prepares flags and environments we can compute for a `rustdoc` invocation +/// before the job queue starts compiling any unit. +/// +/// This builds a static view of the invocation. Flags depending on the +/// completion of other units will be added later in runtime, such as flags +/// from build scripts. +fn prepare_rustdoc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult { + let bcx = build_runner.bcx; + // script_metadata is not needed here, it is only for tests. + let mut rustdoc = build_runner.compilation.rustdoc_process(unit, None)?; + rustdoc.inherit_jobserver(&build_runner.jobserver); + let crate_name = unit.target.crate_name(); + rustdoc.arg("--crate-name").arg(&crate_name); + add_path_args(bcx.ws, unit, &mut rustdoc); + add_cap_lints(bcx, unit, &mut rustdoc); + + if let CompileKind::Target(target) = unit.kind { + rustdoc.arg("--target").arg(target.rustc_target()); + } + let doc_dir = build_runner.files().out_dir(unit); + rustdoc.arg("-o").arg(&doc_dir); + rustdoc.args(&features_args(unit)); + rustdoc.args(&check_cfg_args(unit)); + + add_error_format_and_color(build_runner, &mut rustdoc); + add_allow_features(build_runner, &mut rustdoc); + + if let Some(trim_paths) = unit.profile.trim_paths.as_ref() { + trim_paths_args_rustdoc(&mut rustdoc, build_runner, unit, trim_paths)?; + } + + rustdoc.args(unit.pkg.manifest().lint_rustflags()); + + let metadata = build_runner.metadata_for_doc_units[unit]; + rustdoc + .arg("-C") + .arg(format!("metadata={}", metadata.c_metadata())); + + if unit.mode.is_doc_scrape() { + debug_assert!(build_runner.bcx.scrape_units.contains(unit)); + + if unit.target.is_test() { + rustdoc.arg("--scrape-tests"); + } + + rustdoc.arg("-Zunstable-options"); + + rustdoc + .arg("--scrape-examples-output-path") + .arg(scrape_output_path(build_runner, unit)?); + + // Only scrape example for items from crates in the workspace, to reduce generated file size + for pkg in build_runner.bcx.packages.packages() { + let names = pkg + .targets() + .iter() + .map(|target| target.crate_name()) + .collect::>(); + for name in names { + rustdoc.arg("--scrape-examples-target-crate").arg(name); + } + } + } + + if should_include_scrape_units(build_runner.bcx, unit) { + rustdoc.arg("-Zunstable-options"); + } + + build_deps_args(&mut rustdoc, build_runner, unit)?; + rustdoc::add_root_urls(build_runner, unit, &mut rustdoc)?; + + rustdoc::add_output_format(build_runner, unit, &mut rustdoc)?; + + if let Some(args) = build_runner.bcx.extra_args_for(unit) { + rustdoc.args(args); + } + rustdoc.args(&unit.rustdocflags); + + if !crate_version_flag_already_present(&rustdoc) { + append_crate_version_flag(unit, &mut rustdoc); + } + + Ok(rustdoc) +} + +/// Creates a unit of work invoking `rustdoc` for documenting the `unit`. +fn rustdoc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult { + let mut rustdoc = prepare_rustdoc(build_runner, unit)?; + + let crate_name = unit.target.crate_name(); + let doc_dir = build_runner.files().out_dir(unit); + // Create the documentation directory ahead of time as rustdoc currently has + // a bug where concurrent invocations will race to create this directory if + // it doesn't already exist. + paths::create_dir_all(&doc_dir)?; + + let target_desc = unit.target.description_named(); + let name = unit.pkg.name(); + let build_script_outputs = Arc::clone(&build_runner.build_script_outputs); + let package_id = unit.pkg.package_id(); + let manifest_path = PathBuf::from(unit.pkg.manifest_path()); + let target = Target::clone(&unit.target); + let mut output_options = OutputOptions::new(build_runner, unit); + let script_metadata = build_runner.find_build_script_metadata(unit); + let scrape_outputs = if should_include_scrape_units(build_runner.bcx, unit) { + Some( + build_runner + .bcx + .scrape_units + .iter() + .map(|unit| { + Ok(( + build_runner.files().metadata(unit).unit_id(), + scrape_output_path(build_runner, unit)?, + )) + }) + .collect::>>()?, + ) + } else { + None + }; + + let failed_scrape_units = Arc::clone(&build_runner.failed_scrape_units); + let hide_diagnostics_for_scrape_unit = build_runner.bcx.unit_can_fail_for_docscraping(unit) + && !matches!( + build_runner.bcx.gctx.shell().verbosity(), + Verbosity::Verbose + ); + let failed_scrape_diagnostic = hide_diagnostics_for_scrape_unit.then(|| { + make_failed_scrape_diagnostic( + build_runner, + unit, + format_args!("failed to scan {target_desc} in package `{name}` for example code usage"), + ) + }); + if hide_diagnostics_for_scrape_unit { + output_options.show_diagnostics = false; + } + + Ok(Work::new(move |state| { + add_custom_flags( + &mut rustdoc, + &build_script_outputs.lock().unwrap(), + script_metadata, + )?; + + // Add the output of scraped examples to the rustdoc command. + // This action must happen after the unit's dependencies have finished, + // because some of those deps may be Docscrape units which have failed. + // So we dynamically determine which `--with-examples` flags to pass here. + if let Some(scrape_outputs) = scrape_outputs { + let failed_scrape_units = failed_scrape_units.lock().unwrap(); + for (metadata, output_path) in &scrape_outputs { + if !failed_scrape_units.contains(metadata) { + rustdoc.arg("--with-examples").arg(output_path); + } + } + } + + let crate_dir = doc_dir.join(&crate_name); + if crate_dir.exists() { + // Remove output from a previous build. This ensures that stale + // files for removed items are removed. + debug!("removing pre-existing doc directory {:?}", crate_dir); + paths::remove_dir_all(crate_dir)?; + } + state.running(&rustdoc); + + let result = rustdoc + .exec_with_streaming( + &mut |line| on_stdout_line(state, line, package_id, &target), + &mut |line| { + on_stderr_line( + state, + line, + package_id, + &manifest_path, + &target, + &mut output_options, + ) + }, + false, + ) + .map_err(verbose_if_simple_exit_code) + .with_context(|| format!("could not document `{}`", name)); + + if let Err(e) = result { + if let Some(diagnostic) = failed_scrape_diagnostic { + state.warning(diagnostic)?; + } + + return Err(e); + } + + Ok(()) + })) +} + +// The --crate-version flag could have already been passed in RUSTDOCFLAGS +// or as an extra compiler argument for rustdoc +fn crate_version_flag_already_present(rustdoc: &ProcessBuilder) -> bool { + rustdoc.get_args().any(|flag| { + flag.to_str() + .map_or(false, |flag| flag.starts_with(RUSTDOC_CRATE_VERSION_FLAG)) + }) +} + +fn append_crate_version_flag(unit: &Unit, rustdoc: &mut ProcessBuilder) { + rustdoc + .arg(RUSTDOC_CRATE_VERSION_FLAG) + .arg(unit.pkg.version().to_string()); +} + +/// Adds [`--cap-lints`] to the command to execute. +/// +/// [`--cap-lints`]: https://doc.rust-lang.org/nightly/rustc/lints/levels.html#capping-lints +fn add_cap_lints(bcx: &BuildContext<'_, '_>, unit: &Unit, cmd: &mut ProcessBuilder) { + // If this is an upstream dep we don't want warnings from, turn off all + // lints. + if !unit.show_warnings(bcx.gctx) { + cmd.arg("--cap-lints").arg("allow"); + + // If this is an upstream dep but we *do* want warnings, make sure that they + // don't fail compilation. + } else if !unit.is_local() { + cmd.arg("--cap-lints").arg("warn"); + } +} + +/// Forwards [`-Zallow-features`] if it is set for cargo. +/// +/// [`-Zallow-features`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#allow-features +fn add_allow_features(build_runner: &BuildRunner<'_, '_>, cmd: &mut ProcessBuilder) { + if let Some(allow) = &build_runner.bcx.gctx.cli_unstable().allow_features { + use std::fmt::Write; + let mut arg = String::from("-Zallow-features="); + for f in allow { + let _ = write!(&mut arg, "{f},"); + } + cmd.arg(arg.trim_end_matches(',')); + } +} + +/// Adds [`--error-format`] to the command to execute. +/// +/// Cargo always uses JSON output. This has several benefits, such as being +/// easier to parse, handles changing formats (for replaying cached messages), +/// ensures atomic output (so messages aren't interleaved), allows for +/// intercepting messages like rmeta artifacts, etc. rustc includes a +/// "rendered" field in the JSON message with the message properly formatted, +/// which Cargo will extract and display to the user. +/// +/// [`--error-format`]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#--error-format-control-how-errors-are-produced +fn add_error_format_and_color(build_runner: &BuildRunner<'_, '_>, cmd: &mut ProcessBuilder) { + cmd.arg("--error-format=json"); + let mut json = String::from("--json=diagnostic-rendered-ansi,artifacts,future-incompat"); + + match build_runner.bcx.build_config.message_format { + MessageFormat::Short | MessageFormat::Json { short: true, .. } => { + json.push_str(",diagnostic-short"); + } + _ => {} + } + cmd.arg(json); + + let gctx = build_runner.bcx.gctx; + if let Some(width) = gctx.shell().err_width().diagnostic_terminal_width() { + cmd.arg(format!("--diagnostic-width={width}")); + } +} + +/// Adds essential rustc flags and environment variables to the command to execute. +fn build_base_args( + build_runner: &BuildRunner<'_, '_>, + cmd: &mut ProcessBuilder, + unit: &Unit, +) -> CargoResult<()> { + assert!(!unit.mode.is_run_custom_build()); + + let bcx = build_runner.bcx; + let Profile { + ref opt_level, + codegen_backend, + codegen_units, + debuginfo, + debug_assertions, + split_debuginfo, + overflow_checks, + rpath, + ref panic, + incremental, + strip, + rustflags: profile_rustflags, + trim_paths, + .. + } = unit.profile.clone(); + let test = unit.mode.is_any_test(); + + cmd.arg("--crate-name").arg(&unit.target.crate_name()); + + let edition = unit.target.edition(); + edition.cmd_edition_arg(cmd); + + add_path_args(bcx.ws, unit, cmd); + add_error_format_and_color(build_runner, cmd); + add_allow_features(build_runner, cmd); + + let mut contains_dy_lib = false; + if !test { + for crate_type in &unit.target.rustc_crate_types() { + cmd.arg("--crate-type").arg(crate_type.as_str()); + contains_dy_lib |= crate_type == &CrateType::Dylib; + } + } + + if unit.mode.is_check() { + cmd.arg("--emit=dep-info,metadata"); + } else if !unit.requires_upstream_objects() { + // Always produce metadata files for rlib outputs. Metadata may be used + // in this session for a pipelined compilation, or it may be used in a + // future Cargo session as part of a pipelined compile. + cmd.arg("--emit=dep-info,metadata,link"); + } else { + cmd.arg("--emit=dep-info,link"); + } + + let prefer_dynamic = (unit.target.for_host() && !unit.target.is_custom_build()) + || (contains_dy_lib && !build_runner.is_primary_package(unit)); + if prefer_dynamic { + cmd.arg("-C").arg("prefer-dynamic"); + } + + if opt_level.as_str() != "0" { + cmd.arg("-C").arg(&format!("opt-level={}", opt_level)); + } + + if *panic != PanicStrategy::Unwind { + cmd.arg("-C").arg(format!("panic={}", panic)); + } + + cmd.args(<o_args(build_runner, unit)); + + if let Some(backend) = codegen_backend { + cmd.arg("-Z").arg(&format!("codegen-backend={}", backend)); + } + + if let Some(n) = codegen_units { + cmd.arg("-C").arg(&format!("codegen-units={}", n)); + } + + let debuginfo = debuginfo.into_inner(); + // Shorten the number of arguments if possible. + if debuginfo != TomlDebugInfo::None { + cmd.arg("-C").arg(format!("debuginfo={debuginfo}")); + // This is generally just an optimization on build time so if we don't + // pass it then it's ok. The values for the flag (off, packed, unpacked) + // may be supported or not depending on the platform, so availability is + // checked per-value. For example, at the time of writing this code, on + // Windows the only stable valid value for split-debuginfo is "packed", + // while on Linux "unpacked" is also stable. + if let Some(split) = split_debuginfo { + if build_runner + .bcx + .target_data + .info(unit.kind) + .supports_debuginfo_split(split) + { + cmd.arg("-C").arg(format!("split-debuginfo={split}")); + } + } + } + + if let Some(trim_paths) = trim_paths { + trim_paths_args(cmd, build_runner, unit, &trim_paths)?; + } + + cmd.args(unit.pkg.manifest().lint_rustflags()); + cmd.args(&profile_rustflags); + + // `-C overflow-checks` is implied by the setting of `-C debug-assertions`, + // so we only need to provide `-C overflow-checks` if it differs from + // the value of `-C debug-assertions` we would provide. + if opt_level.as_str() != "0" { + if debug_assertions { + cmd.args(&["-C", "debug-assertions=on"]); + if !overflow_checks { + cmd.args(&["-C", "overflow-checks=off"]); + } + } else if overflow_checks { + cmd.args(&["-C", "overflow-checks=on"]); + } + } else if !debug_assertions { + cmd.args(&["-C", "debug-assertions=off"]); + if overflow_checks { + cmd.args(&["-C", "overflow-checks=on"]); + } + } else if !overflow_checks { + cmd.args(&["-C", "overflow-checks=off"]); + } + + if test && unit.target.harness() { + cmd.arg("--test"); + + // Cargo has historically never compiled `--test` binaries with + // `panic=abort` because the `test` crate itself didn't support it. + // Support is now upstream, however, but requires an unstable flag to be + // passed when compiling the test. We require, in Cargo, an unstable + // flag to pass to rustc, so register that here. Eventually this flag + // will simply not be needed when the behavior is stabilized in the Rust + // compiler itself. + if *panic == PanicStrategy::Abort { + cmd.arg("-Z").arg("panic-abort-tests"); + } + } else if test { + cmd.arg("--cfg").arg("test"); + } + + cmd.args(&features_args(unit)); + cmd.args(&check_cfg_args(unit)); + + let meta = build_runner.files().metadata(unit); + cmd.arg("-C") + .arg(&format!("metadata={}", meta.c_metadata())); + if let Some(c_extra_filename) = meta.c_extra_filename() { + cmd.arg("-C") + .arg(&format!("extra-filename=-{c_extra_filename}")); + } + + if rpath { + cmd.arg("-C").arg("rpath"); + } + + cmd.arg("--out-dir") + .arg(&build_runner.files().out_dir(unit)); + + fn opt(cmd: &mut ProcessBuilder, key: &str, prefix: &str, val: Option<&OsStr>) { + if let Some(val) = val { + let mut joined = OsString::from(prefix); + joined.push(val); + cmd.arg(key).arg(joined); + } + } + + if let CompileKind::Target(n) = unit.kind { + cmd.arg("--target").arg(n.rustc_target()); + } + + opt( + cmd, + "-C", + "linker=", + build_runner + .compilation + .target_linker(unit.kind) + .as_ref() + .map(|s| s.as_ref()), + ); + if incremental { + let dir = build_runner + .files() + .layout(unit.kind) + .incremental() + .as_os_str(); + opt(cmd, "-C", "incremental=", Some(dir)); + } + + let strip = strip.into_inner(); + if strip != StripInner::None { + cmd.arg("-C").arg(format!("strip={}", strip)); + } + + if unit.is_std { + // -Zforce-unstable-if-unmarked prevents the accidental use of + // unstable crates within the sysroot (such as "extern crate libc" or + // any non-public crate in the sysroot). + // + // RUSTC_BOOTSTRAP allows unstable features on stable. + cmd.arg("-Z") + .arg("force-unstable-if-unmarked") + .env("RUSTC_BOOTSTRAP", "1"); + } + + // Add `CARGO_BIN_EXE_` environment variables for building tests. + if unit.target.is_test() || unit.target.is_bench() { + for bin_target in unit + .pkg + .manifest() + .targets() + .iter() + .filter(|target| target.is_bin()) + { + let exe_path = build_runner.files().bin_link_for_target( + bin_target, + unit.kind, + build_runner.bcx, + )?; + let name = bin_target + .binary_filename() + .unwrap_or(bin_target.name().to_string()); + let key = format!("CARGO_BIN_EXE_{}", name); + cmd.env(&key, exe_path); + } + } + Ok(()) +} + +/// All active features for the unit passed as `--cfg features=`. +fn features_args(unit: &Unit) -> Vec { + let mut args = Vec::with_capacity(unit.features.len() * 2); + + for feat in &unit.features { + args.push(OsString::from("--cfg")); + args.push(OsString::from(format!("feature=\"{}\"", feat))); + } + + args +} + +/// Like [`trim_paths_args`] but for rustdoc invocations. +fn trim_paths_args_rustdoc( + cmd: &mut ProcessBuilder, + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + trim_paths: &TomlTrimPaths, +) -> CargoResult<()> { + match trim_paths { + // rustdoc supports diagnostics trimming only. + TomlTrimPaths::Values(values) if !values.contains(&TomlTrimPathsValue::Diagnostics) => { + return Ok(()) + } + _ => {} + } + + // feature gate was checked during manifest/config parsing. + cmd.arg("-Zunstable-options"); + + // Order of `--remap-path-prefix` flags is important for `-Zbuild-std`. + // We want to show `/rustc//library/std` instead of `std-0.0.0`. + cmd.arg(package_remap(build_runner, unit)); + cmd.arg(sysroot_remap(build_runner, unit)); + + Ok(()) +} + +/// Generates the `--remap-path-scope` and `--remap-path-prefix` for [RFC 3127]. +/// See also unstable feature [`-Ztrim-paths`]. +/// +/// [RFC 3127]: https://rust-lang.github.io/rfcs/3127-trim-paths.html +/// [`-Ztrim-paths`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#profile-trim-paths-option +fn trim_paths_args( + cmd: &mut ProcessBuilder, + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + trim_paths: &TomlTrimPaths, +) -> CargoResult<()> { + if trim_paths.is_none() { + return Ok(()); + } + + // feature gate was checked during manifest/config parsing. + cmd.arg("-Zunstable-options"); + cmd.arg(format!("-Zremap-path-scope={trim_paths}")); + + // Order of `--remap-path-prefix` flags is important for `-Zbuild-std`. + // We want to show `/rustc//library/std` instead of `std-0.0.0`. + cmd.arg(package_remap(build_runner, unit)); + cmd.arg(sysroot_remap(build_runner, unit)); + + Ok(()) +} + +/// Path prefix remap rules for sysroot. +/// +/// This remap logic aligns with rustc: +/// +fn sysroot_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> OsString { + let mut remap = OsString::from("--remap-path-prefix="); + remap.push({ + // See also `detect_sysroot_src_path()`. + let mut sysroot = build_runner.bcx.target_data.info(unit.kind).sysroot.clone(); + sysroot.push("lib"); + sysroot.push("rustlib"); + sysroot.push("src"); + sysroot.push("rust"); + sysroot + }); + remap.push("="); + remap.push("/rustc/"); + if let Some(commit_hash) = build_runner.bcx.rustc().commit_hash.as_ref() { + remap.push(commit_hash); + } else { + remap.push(build_runner.bcx.rustc().version.to_string()); + } + remap +} + +/// Path prefix remap rules for dependencies. +/// +/// * Git dependencies: remove `~/.cargo/git/checkouts` prefix. +/// * Registry dependencies: remove `~/.cargo/registry/src` prefix. +/// * Others (e.g. path dependencies): +/// * relative paths to workspace root if inside the workspace directory. +/// * otherwise remapped to `-`. +fn package_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> OsString { + let pkg_root = unit.pkg.root(); + let ws_root = build_runner.bcx.ws.root(); + let mut remap = OsString::from("--remap-path-prefix="); + let source_id = unit.pkg.package_id().source_id(); + if source_id.is_git() { + remap.push( + build_runner + .bcx + .gctx + .git_checkouts_path() + .as_path_unlocked(), + ); + remap.push("="); + } else if source_id.is_registry() { + remap.push( + build_runner + .bcx + .gctx + .registry_source_path() + .as_path_unlocked(), + ); + remap.push("="); + } else if pkg_root.strip_prefix(ws_root).is_ok() { + remap.push(ws_root); + remap.push("=."); // remap to relative rustc work dir explicitly + } else { + remap.push(pkg_root); + remap.push("="); + remap.push(unit.pkg.name()); + remap.push("-"); + remap.push(unit.pkg.version().to_string()); + } + remap +} + +/// Generates the `--check-cfg` arguments for the `unit`. +fn check_cfg_args(unit: &Unit) -> Vec { + // The routine below generates the --check-cfg arguments. Our goals here are to + // enable the checking of conditionals and pass the list of declared features. + // + // In the simplified case, it would resemble something like this: + // + // --check-cfg=cfg() --check-cfg=cfg(feature, values(...)) + // + // but having `cfg()` is redundant with the second argument (as well-known names + // and values are implicitly enabled when one or more `--check-cfg` argument is + // passed) so we don't emit it and just pass: + // + // --check-cfg=cfg(feature, values(...)) + // + // This way, even if there are no declared features, the config `feature` will + // still be expected, meaning users would get "unexpected value" instead of name. + // This wasn't always the case, see rust-lang#119930 for some details. + + let gross_cap_estimation = unit.pkg.summary().features().len() * 7 + 25; + let mut arg_feature = OsString::with_capacity(gross_cap_estimation); + + arg_feature.push("cfg(feature, values("); + for (i, feature) in unit.pkg.summary().features().keys().enumerate() { + if i != 0 { + arg_feature.push(", "); + } + arg_feature.push("\""); + arg_feature.push(feature); + arg_feature.push("\""); + } + arg_feature.push("))"); + + // In addition to the package features, we also include the `test` cfg (since + // compiler-team#785, as to be able to someday apply yt conditionaly), as well + // the `docsrs` cfg from the docs.rs service. + // + // We include `docsrs` here (in Cargo) instead of rustc, since there is a much closer + // relationship between Cargo and docs.rs than rustc and docs.rs. In particular, all + // users of docs.rs use Cargo, but not all users of rustc (like Rust-for-Linux) use docs.rs. + + vec![ + OsString::from("--check-cfg"), + OsString::from("cfg(docsrs,test)"), + OsString::from("--check-cfg"), + arg_feature, + ] +} + +/// Adds LTO related codegen flags. +fn lto_args(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> Vec { + let mut result = Vec::new(); + let mut push = |arg: &str| { + result.push(OsString::from("-C")); + result.push(OsString::from(arg)); + }; + match build_runner.lto[unit] { + lto::Lto::Run(None) => push("lto"), + lto::Lto::Run(Some(s)) => push(&format!("lto={}", s)), + lto::Lto::Off => { + push("lto=off"); + push("embed-bitcode=no"); + } + lto::Lto::ObjectAndBitcode => {} // this is rustc's default + lto::Lto::OnlyBitcode => push("linker-plugin-lto"), + lto::Lto::OnlyObject => push("embed-bitcode=no"), + } + result +} + +/// Adds dependency-relevant rustc flags and environment variables +/// to the command to execute, such as [`-L`] and [`--extern`]. +/// +/// [`-L`]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#-l-add-a-directory-to-the-library-search-path +/// [`--extern`]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#--extern-specify-where-an-external-library-is-located +fn build_deps_args( + cmd: &mut ProcessBuilder, + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, +) -> CargoResult<()> { + let bcx = build_runner.bcx; + cmd.arg("-L").arg(&{ + let mut deps = OsString::from("dependency="); + deps.push(build_runner.files().deps_dir(unit)); + deps + }); + + // Be sure that the host path is also listed. This'll ensure that proc macro + // dependencies are correctly found (for reexported macros). + if !unit.kind.is_host() { + cmd.arg("-L").arg(&{ + let mut deps = OsString::from("dependency="); + deps.push(build_runner.files().host_deps()); + deps + }); + } + + let deps = build_runner.unit_deps(unit); + + // If there is not one linkable target but should, rustc fails later + // on if there is an `extern crate` for it. This may turn into a hard + // error in the future (see PR #4797). + if !deps + .iter() + .any(|dep| !dep.unit.mode.is_doc() && dep.unit.target.is_linkable()) + { + if let Some(dep) = deps.iter().find(|dep| { + !dep.unit.mode.is_doc() && dep.unit.target.is_lib() && !dep.unit.artifact.is_true() + }) { + bcx.gctx.shell().warn(format!( + "The package `{}` \ + provides no linkable target. The compiler might raise an error while compiling \ + `{}`. Consider adding 'dylib' or 'rlib' to key `crate-type` in `{}`'s \ + Cargo.toml. This warning might turn into a hard error in the future.", + dep.unit.target.crate_name(), + unit.target.crate_name(), + dep.unit.target.crate_name() + ))?; + } + } + + let mut unstable_opts = false; + + for dep in deps { + if dep.unit.mode.is_run_custom_build() { + cmd.env( + "OUT_DIR", + &build_runner.files().build_script_out_dir(&dep.unit), + ); + } + } + + for arg in extern_args(build_runner, unit, &mut unstable_opts)? { + cmd.arg(arg); + } + + for (var, env) in artifact::get_env(build_runner, deps)? { + cmd.env(&var, env); + } + + // This will only be set if we're already using a feature + // requiring nightly rust + if unstable_opts { + cmd.arg("-Z").arg("unstable-options"); + } + + Ok(()) +} + +/// Adds extra rustc flags and environment variables collected from the output +/// of a build-script to the command to execute, include custom environment +/// variables and `cfg`. +fn add_custom_flags( + cmd: &mut ProcessBuilder, + build_script_outputs: &BuildScriptOutputs, + metadata: Option, +) -> CargoResult<()> { + if let Some(metadata) = metadata { + if let Some(output) = build_script_outputs.get(metadata) { + for cfg in output.cfgs.iter() { + cmd.arg("--cfg").arg(cfg); + } + for check_cfg in &output.check_cfgs { + cmd.arg("--check-cfg").arg(check_cfg); + } + for (name, value) in output.env.iter() { + cmd.env(name, value); + } + } + } + + Ok(()) +} + +/// Generates a list of `--extern` arguments. +pub fn extern_args( + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + unstable_opts: &mut bool, +) -> CargoResult> { + let mut result = Vec::new(); + let deps = build_runner.unit_deps(unit); + + // Closure to add one dependency to `result`. + let mut link_to = + |dep: &UnitDep, extern_crate_name: InternedString, noprelude: bool| -> CargoResult<()> { + let mut value = OsString::new(); + let mut opts = Vec::new(); + let is_public_dependency_enabled = unit + .pkg + .manifest() + .unstable_features() + .require(Feature::public_dependency()) + .is_ok() + || build_runner.bcx.gctx.cli_unstable().public_dependency; + if !dep.public && unit.target.is_lib() && is_public_dependency_enabled { + opts.push("priv"); + *unstable_opts = true; + } + if noprelude { + opts.push("noprelude"); + *unstable_opts = true; + } + if !opts.is_empty() { + value.push(opts.join(",")); + value.push(":"); + } + value.push(extern_crate_name.as_str()); + value.push("="); + + let mut pass = |file| { + let mut value = value.clone(); + value.push(file); + result.push(OsString::from("--extern")); + result.push(value); + }; + + let outputs = build_runner.outputs(&dep.unit)?; + + if build_runner.only_requires_rmeta(unit, &dep.unit) || dep.unit.mode.is_check() { + // Example: rlib dependency for an rlib, rmeta is all that is required. + let output = outputs + .iter() + .find(|output| output.flavor == FileFlavor::Rmeta) + .expect("failed to find rmeta dep for pipelined dep"); + pass(&output.path); + } else { + // Example: a bin needs `rlib` for dependencies, it cannot use rmeta. + for output in outputs.iter() { + if output.flavor == FileFlavor::Linkable { + pass(&output.path); + } + } + } + Ok(()) + }; + + for dep in deps { + if dep.unit.target.is_linkable() && !dep.unit.mode.is_doc() { + link_to(dep, dep.extern_crate_name, dep.noprelude)?; + } + } + if unit.target.proc_macro() { + // Automatically import `proc_macro`. + result.push(OsString::from("--extern")); + result.push(OsString::from("proc_macro")); + } + + Ok(result) +} + +fn envify(s: &str) -> String { + s.chars() + .flat_map(|c| c.to_uppercase()) + .map(|c| if c == '-' { '_' } else { c }) + .collect() +} + +/// Configuration of the display of messages emitted by the compiler, +/// e.g. diagnostics, warnings, errors, and message caching. +struct OutputOptions { + /// What format we're emitting from Cargo itself. + format: MessageFormat, + /// 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 + /// be cached (such as when replaying cached messages). + cache_cell: Option<(PathBuf, LazyCell)>, + /// If `true`, display any diagnostics. + /// Other types of JSON messages are processed regardless + /// of the value of this flag. + /// + /// This is used primarily for cache replay. If you build with `-vv`, the + /// cache will be filled with diagnostics from dependencies. When the + /// cache is replayed without `-vv`, we don't want to show them. + show_diagnostics: bool, + /// Tracks the number of warnings we've seen so far. + warnings_seen: usize, + /// Tracks the number of errors we've seen so far. + errors_seen: usize, +} + +impl OutputOptions { + fn new(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> OutputOptions { + let path = build_runner.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())); + let show_diagnostics = + build_runner.bcx.gctx.warning_handling().unwrap_or_default() != WarningHandling::Allow; + OutputOptions { + format: build_runner.bcx.build_config.message_format, + cache_cell, + show_diagnostics, + warnings_seen: 0, + errors_seen: 0, + } + } +} + +fn on_stdout_line( + state: &JobState<'_, '_>, + line: &str, + _package_id: PackageId, + _target: &Target, +) -> CargoResult<()> { + state.stdout(line.to_string())?; + Ok(()) +} + +fn on_stderr_line( + state: &JobState<'_, '_>, + line: &str, + package_id: PackageId, + manifest_path: &std::path::Path, + target: &Target, + options: &mut OutputOptions, +) -> CargoResult<()> { + if on_stderr_line_inner(state, line, package_id, manifest_path, target, options)? { + // Check if caching is enabled. + if let Some((path, cell)) = &mut options.cache_cell { + // Cache the output, which will be replayed later when Fresh. + let f = cell.try_borrow_mut_with(|| paths::create(path))?; + debug_assert!(!line.contains('\n')); + f.write_all(line.as_bytes())?; + f.write_all(&[b'\n'])?; + } + } + Ok(()) +} + +/// Returns true if the line should be cached. +fn on_stderr_line_inner( + state: &JobState<'_, '_>, + line: &str, + package_id: PackageId, + manifest_path: &std::path::Path, + target: &Target, + options: &mut OutputOptions, +) -> CargoResult { + // We primarily want to use this function to process JSON messages from + // rustc. The compiler should always print one JSON message per line, and + // otherwise it may have other output intermingled (think RUST_LOG or + // something like that), so skip over everything that doesn't look like a + // JSON message. + if !line.starts_with('{') { + state.stderr(line.to_string())?; + return Ok(true); + } + + let mut compiler_message: Box = match serde_json::from_str(line) { + Ok(msg) => msg, + + // If the compiler produced a line that started with `{` but it wasn't + // valid JSON, maybe it wasn't JSON in the first place! Forward it along + // to stderr. + Err(e) => { + debug!("failed to parse json: {:?}", e); + state.stderr(line.to_string())?; + return Ok(true); + } + }; + + let count_diagnostic = |level, options: &mut OutputOptions| { + if level == "warning" { + options.warnings_seen += 1; + } else if level == "error" { + options.errors_seen += 1; + } + }; + + if let Ok(report) = serde_json::from_str::(compiler_message.get()) { + for item in &report.future_incompat_report { + count_diagnostic(&*item.diagnostic.level, options); + } + state.future_incompat_report(report.future_incompat_report); + return Ok(true); + } + + // Depending on what we're emitting from Cargo itself, we figure out what to + // do with this JSON message. + match options.format { + // In the "human" output formats (human/short) or if diagnostic messages + // from rustc aren't being included in the output of Cargo's JSON + // messages then we extract the diagnostic (if present) here and handle + // it ourselves. + MessageFormat::Human + | MessageFormat::Short + | MessageFormat::Json { + render_diagnostics: true, + .. + } => { + #[derive(serde::Deserialize)] + struct CompilerMessage<'a> { + // `rendered` contains escape sequences, which can't be + // zero-copy deserialized by serde_json. + // See https://github.com/serde-rs/json/issues/742 + rendered: String, + #[serde(borrow)] + message: Cow<'a, str>, + #[serde(borrow)] + level: Cow<'a, str>, + children: Vec, + } + + // A partial rustfix::diagnostics::Diagnostic. We deserialize only a + // subset of the fields because rustc's output can be extremely + // deeply nested JSON in pathological cases involving macro + // expansion. Rustfix's Diagnostic struct is recursive containing a + // field `children: Vec`, and it can cause deserialization to + // hit serde_json's default recursion limit, or overflow the stack + // if we turn that off. Cargo only cares about the 1 field listed + // here. + #[derive(serde::Deserialize)] + struct PartialDiagnostic { + spans: Vec, + } + + // A partial rustfix::diagnostics::DiagnosticSpan. + #[derive(serde::Deserialize)] + struct PartialDiagnosticSpan { + suggestion_applicability: Option, + } + + if let Ok(mut msg) = serde_json::from_str::>(compiler_message.get()) + { + if msg.message.starts_with("aborting due to") + || msg.message.ends_with("warning emitted") + || msg.message.ends_with("warnings emitted") + { + // Skip this line; we'll print our own summary at the end. + return Ok(true); + } + // state.stderr will add a newline + if msg.rendered.ends_with('\n') { + msg.rendered.pop(); + } + let rendered = msg.rendered; + if options.show_diagnostics { + let machine_applicable: bool = msg + .children + .iter() + .map(|child| { + child + .spans + .iter() + .filter_map(|span| span.suggestion_applicability) + .any(|app| app == Applicability::MachineApplicable) + }) + .any(|b| b); + count_diagnostic(&msg.level, options); + state.emit_diag(&msg.level, rendered, machine_applicable)?; + } + return Ok(true); + } + } + + // Remove color information from the rendered string if color is not + // enabled. Cargo always asks for ANSI colors from rustc. This allows + // cached replay to enable/disable colors without re-invoking rustc. + MessageFormat::Json { ansi: false, .. } => { + #[derive(serde::Deserialize, serde::Serialize)] + struct CompilerMessage<'a> { + rendered: String, + #[serde(flatten, borrow)] + other: std::collections::BTreeMap, serde_json::Value>, + } + if let Ok(mut error) = + serde_json::from_str::>(compiler_message.get()) + { + error.rendered = anstream::adapter::strip_str(&error.rendered).to_string(); + let new_line = serde_json::to_string(&error)?; + compiler_message = serde_json::value::RawValue::from_string(new_line)?; + } + } + + // If ansi colors are desired then we should be good to go! We can just + // pass through this message as-is. + MessageFormat::Json { ansi: true, .. } => {} + } + + // We always tell rustc to emit messages about artifacts being produced. + // These messages feed into pipelined compilation, as well as timing + // information. + // + // Look for a matching directive and inform Cargo internally that a + // metadata file has been produced. + #[derive(serde::Deserialize)] + struct ArtifactNotification<'a> { + #[serde(borrow)] + artifact: Cow<'a, str>, + } + + if let Ok(artifact) = serde_json::from_str::>(compiler_message.get()) { + trace!("found directive from rustc: `{}`", artifact.artifact); + if artifact.artifact.ends_with(".rmeta") { + debug!("looks like metadata finished early!"); + state.rmeta_produced(); + } + return Ok(false); + } + + // And failing all that above we should have a legitimate JSON diagnostic + // from the compiler, so wrap it in an external Cargo JSON message + // indicating which package it came from and then emit it. + + if !options.show_diagnostics { + return Ok(true); + } + + #[derive(serde::Deserialize)] + struct CompilerMessage<'a> { + #[serde(borrow)] + message: Cow<'a, str>, + #[serde(borrow)] + level: Cow<'a, str>, + } + + if let Ok(msg) = serde_json::from_str::>(compiler_message.get()) { + if msg.message.starts_with("aborting due to") + || msg.message.ends_with("warning emitted") + || msg.message.ends_with("warnings emitted") + { + // Skip this line; we'll print our own summary at the end. + return Ok(true); + } + count_diagnostic(&msg.level, options); + } + + let msg = machine_message::FromCompiler { + package_id: package_id.to_spec(), + manifest_path, + target, + message: compiler_message, + } + .to_json_string(); + + // Switch json lines from rustc/rustdoc that appear on stderr to stdout + // instead. We want the stdout of Cargo to always be machine parseable as + // stderr has our colorized human-readable messages. + state.stdout(msg)?; + Ok(true) +} + +/// Creates a unit of work that replays the cached compiler message. +/// +/// Usually used when a job is fresh and doesn't need to recompile. +fn replay_output_cache( + package_id: PackageId, + manifest_path: PathBuf, + target: &Target, + path: PathBuf, + format: MessageFormat, + show_diagnostics: bool, +) -> Work { + let target = target.clone(); + let mut options = OutputOptions { + format, + cache_cell: None, + show_diagnostics, + warnings_seen: 0, + errors_seen: 0, + }; + Work::new(move |state| { + if !path.exists() { + // No cached output, probably didn't emit anything. + return Ok(()); + } + // We sometimes have gigabytes of output from the compiler, so avoid + // loading it all into memory at once, as that can cause OOM where + // otherwise there would be none. + let file = paths::open(&path)?; + let mut reader = std::io::BufReader::new(file); + let mut line = String::new(); + loop { + let length = reader.read_line(&mut line)?; + if length == 0 { + break; + } + let trimmed = line.trim_end_matches(&['\n', '\r'][..]); + on_stderr_line( + state, + trimmed, + package_id, + &manifest_path, + &target, + &mut options, + )?; + line.clear(); + } + Ok(()) + }) +} + +/// Provides a package name with descriptive target information, +/// e.g., '`foo` (bin "bar" test)', '`foo` (lib doctest)'. +fn descriptive_pkg_name(name: &str, target: &Target, mode: &CompileMode) -> String { + let desc_name = target.description_named(); + let mode = if mode.is_rustc_test() && !(target.is_test() || target.is_bench()) { + " test" + } else if mode.is_doc_test() { + " doctest" + } else if mode.is_doc() { + " doc" + } else { + "" + }; + format!("`{name}` ({desc_name}{mode})") +} + +/// Applies environment variables from config `[env]` to [`ProcessBuilder`]. +pub(crate) fn apply_env_config( + gctx: &crate::GlobalContext, + cmd: &mut ProcessBuilder, +) -> CargoResult<()> { + for (key, value) in gctx.env_config()?.iter() { + // never override a value that has already been set by cargo + if cmd.get_envs().contains_key(key) { + continue; + } + cmd.env(key, value); + } + Ok(()) +} + +/// Checks if there are some scrape units waiting to be processed. +fn should_include_scrape_units(bcx: &BuildContext<'_, '_>, unit: &Unit) -> bool { + unit.mode.is_doc() && bcx.scrape_units.len() > 0 && bcx.ws.unit_needs_doc_scrape(unit) +} + +/// Gets the file path of function call information output from `rustdoc`. +fn scrape_output_path(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult { + assert!(unit.mode.is_doc() || unit.mode.is_doc_scrape()); + build_runner + .outputs(unit) + .map(|outputs| outputs[0].path.clone()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/output_depinfo.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/output_depinfo.rs new file mode 100644 index 000000000..d9efbaae3 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/output_depinfo.rs @@ -0,0 +1,184 @@ +//! dep-info files for external build system integration. +//! See [`output_depinfo`] for more. + +use cargo_util::paths::normalize_path; +use std::collections::{BTreeSet, HashSet}; +use std::io::{BufWriter, Write}; +use std::path::{Path, PathBuf}; + +use super::{fingerprint, BuildRunner, FileFlavor, Unit}; +use crate::util::{internal, CargoResult}; +use cargo_util::paths; +use tracing::debug; + +/// Bacially just normalizes a given path and converts it to a string. +fn render_filename>(path: P, basedir: Option<&str>) -> CargoResult { + fn wrap_path(path: &Path) -> CargoResult { + path.to_str() + .ok_or_else(|| internal(format!("path `{:?}` not utf-8", path))) + .map(|f| f.replace(" ", "\\ ")) + } + + let path = path.as_ref(); + if let Some(basedir) = basedir { + let norm_path = normalize_path(path); + let norm_basedir = normalize_path(basedir.as_ref()); + match norm_path.strip_prefix(norm_basedir) { + Ok(relpath) => wrap_path(relpath), + _ => wrap_path(path), + } + } else { + wrap_path(path) + } +} + +/// Collects all dependencies of the `unit` for the output dep info file. +/// +/// Dependencies will be stored in `deps`, including: +/// +/// * dependencies from [fingerprint dep-info] +/// * paths from `rerun-if-changed` build script instruction +/// * ...and traverse transitive dependencies recursively +/// +/// [fingerprint dep-info]: super::fingerprint#fingerprint-dep-info-files +fn add_deps_for_unit( + deps: &mut BTreeSet, + build_runner: &mut BuildRunner<'_, '_>, + unit: &Unit, + visited: &mut HashSet, +) -> CargoResult<()> { + if !visited.insert(unit.clone()) { + return Ok(()); + } + + // units representing the execution of a build script don't actually + // generate a dep info file, so we just keep on going below + if !unit.mode.is_run_custom_build() { + // Add dependencies from rustc dep-info output (stored in fingerprint directory) + let dep_info_loc = fingerprint::dep_info_loc(build_runner, unit); + if let Some(paths) = fingerprint::parse_dep_info( + unit.pkg.root(), + build_runner.files().host_root(), + &dep_info_loc, + )? { + for path in paths.files.into_keys() { + deps.insert(path); + } + } else { + debug!( + "can't find dep_info for {:?} {}", + unit.pkg.package_id(), + unit.target + ); + return Err(internal("dep_info missing")); + } + } + + // Add rerun-if-changed dependencies + if let Some(metadata) = build_runner.find_build_script_metadata(unit) { + if let Some(output) = build_runner + .build_script_outputs + .lock() + .unwrap() + .get(metadata) + { + for path in &output.rerun_if_changed { + // The paths we have saved from the unit are of arbitrary relativeness and may be + // relative to the crate root of the dependency. + let path = unit.pkg.root().join(path); + deps.insert(path); + } + } + } + + // Recursively traverse all transitive dependencies + let unit_deps = Vec::from(build_runner.unit_deps(unit)); // Create vec due to mutable borrow. + for dep in unit_deps { + if dep.unit.is_local() { + add_deps_for_unit(deps, build_runner, &dep.unit, visited)?; + } + } + Ok(()) +} + +/// Save a `.d` dep-info file for the given unit. This is the third kind of +/// dep-info mentioned in [`fingerprint`] module. +/// +/// Argument `unit` is expected to be the root unit, which will be uplifted. +/// +/// Cargo emits its own dep-info files in the output directory. This is +/// only done for every "uplifted" artifact. These are intended to be used +/// with external build systems so that they can detect if Cargo needs to be +/// re-executed. +/// +/// It includes all the entries from the `rustc` dep-info file, and extends it +/// with any `rerun-if-changed` entries from build scripts. It also includes +/// sources from any path dependencies. Registry dependencies are not included +/// under the assumption that changes to them can be detected via changes to +/// `Cargo.lock`. +/// +/// [`fingerprint`]: super::fingerprint#dep-info-files +pub fn output_depinfo(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult<()> { + let bcx = build_runner.bcx; + let mut deps = BTreeSet::new(); + let mut visited = HashSet::new(); + let success = add_deps_for_unit(&mut deps, build_runner, unit, &mut visited).is_ok(); + let basedir_string; + let basedir = match bcx.gctx.build_config()?.dep_info_basedir.clone() { + Some(value) => { + basedir_string = value + .resolve_path(bcx.gctx) + .as_os_str() + .to_str() + .ok_or_else(|| anyhow::format_err!("build.dep-info-basedir path not utf-8"))? + .to_string(); + Some(basedir_string.as_str()) + } + None => None, + }; + let deps = deps + .iter() + .map(|f| render_filename(f, basedir)) + .collect::>>()?; + + for output in build_runner + .outputs(unit)? + .iter() + .filter(|o| !matches!(o.flavor, FileFlavor::DebugInfo | FileFlavor::Auxiliary)) + { + if let Some(ref link_dst) = output.hardlink { + let output_path = link_dst.with_extension("d"); + if success { + let target_fn = render_filename(link_dst, basedir)?; + + // If nothing changed don't recreate the file which could alter + // its mtime + if let Ok(previous) = fingerprint::parse_rustc_dep_info(&output_path) { + if previous + .files + .iter() + .map(|(path, _checksum)| path) + .eq(deps.iter().map(Path::new)) + { + continue; + } + } + + // Otherwise write it all out + let mut outfile = BufWriter::new(paths::create(output_path)?); + write!(outfile, "{}:", target_fn)?; + for dep in &deps { + write!(outfile, " {}", dep)?; + } + writeln!(outfile)?; + + // dep-info generation failed, so delete output file. This will + // usually cause the build system to always rerun the build + // rule, which is correct if inefficient. + } else if output_path.exists() { + paths::remove_file(output_path)?; + } + } + } + Ok(()) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/rustdoc.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/rustdoc.rs new file mode 100644 index 000000000..7a856fe1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/rustdoc.rs @@ -0,0 +1,335 @@ +//! Utilities for building with rustdoc. + +use crate::core::compiler::build_runner::BuildRunner; +use crate::core::compiler::unit::Unit; +use crate::core::compiler::{BuildContext, CompileKind}; +use crate::sources::CRATES_IO_REGISTRY; +use crate::util::errors::{internal, CargoResult}; +use cargo_util::ProcessBuilder; +use std::collections::HashMap; +use std::collections::HashSet; +use std::fmt; +use std::hash; +use url::Url; + +use super::CompileMode; + +const DOCS_RS_URL: &'static str = "https://docs.rs/"; + +/// Mode used for `std`. This is for unstable feature [`-Zrustdoc-map`][1]. +/// +/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-map +#[derive(Debug, Hash)] +pub enum RustdocExternMode { + /// Use a local `file://` URL. + Local, + /// Use a remote URL to (default). + Remote, + /// An arbitrary URL. + Url(String), +} + +impl From for RustdocExternMode { + fn from(s: String) -> RustdocExternMode { + match s.as_ref() { + "local" => RustdocExternMode::Local, + "remote" => RustdocExternMode::Remote, + _ => RustdocExternMode::Url(s), + } + } +} + +impl fmt::Display for RustdocExternMode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + RustdocExternMode::Local => "local".fmt(f), + RustdocExternMode::Remote => "remote".fmt(f), + RustdocExternMode::Url(s) => s.fmt(f), + } + } +} + +impl<'de> serde::de::Deserialize<'de> for RustdocExternMode { + fn deserialize(deserializer: D) -> Result + where + D: serde::de::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(s.into()) + } +} + +/// A map of registry names to URLs where documentations are hosted. +/// This is for unstable feature [`-Zrustdoc-map`][1]. +/// +/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-map +#[derive(serde::Deserialize, Debug)] +#[serde(default)] +pub struct RustdocExternMap { + #[serde(deserialize_with = "default_crates_io_to_docs_rs")] + /// * Key is the registry name in the configuration `[registries.]`. + /// * Value is the URL where the documentation is hosted. + registries: HashMap, + std: Option, +} + +impl Default for RustdocExternMap { + fn default() -> Self { + Self { + registries: HashMap::from([(CRATES_IO_REGISTRY.into(), DOCS_RS_URL.into())]), + std: None, + } + } +} + +fn default_crates_io_to_docs_rs<'de, D: serde::Deserializer<'de>>( + de: D, +) -> Result, D::Error> { + use serde::Deserialize; + let mut registries = HashMap::deserialize(de)?; + if !registries.contains_key(CRATES_IO_REGISTRY) { + registries.insert(CRATES_IO_REGISTRY.into(), DOCS_RS_URL.into()); + } + Ok(registries) +} + +impl hash::Hash for RustdocExternMap { + fn hash(&self, into: &mut H) { + self.std.hash(into); + for (key, value) in &self.registries { + key.hash(into); + value.hash(into); + } + } +} + +/// Recursively generate html root url for all units and their children. +/// +/// This is needed because in case there is a reexport of foreign reexport, you +/// need to have information about grand-children deps level (deps of your deps). +fn build_all_urls( + build_runner: &BuildRunner<'_, '_>, + rustdoc: &mut ProcessBuilder, + unit: &Unit, + name2url: &HashMap<&String, Url>, + map: &RustdocExternMap, + unstable_opts: &mut bool, + seen: &mut HashSet, +) { + for dep in build_runner.unit_deps(unit) { + if !seen.insert(dep.unit.clone()) { + continue; + } + if !dep.unit.target.is_linkable() || dep.unit.mode.is_doc() { + continue; + } + for (registry, location) in &map.registries { + let sid = dep.unit.pkg.package_id().source_id(); + let matches_registry = || -> bool { + if !sid.is_registry() { + return false; + } + if sid.is_crates_io() { + return registry == CRATES_IO_REGISTRY; + } + if let Some(index_url) = name2url.get(registry) { + return index_url == sid.url(); + } + false + }; + if matches_registry() { + let mut url = location.clone(); + if !url.contains("{pkg_name}") && !url.contains("{version}") { + if !url.ends_with('/') { + url.push('/'); + } + url.push_str("{pkg_name}/{version}/"); + } + let url = url + .replace("{pkg_name}", &dep.unit.pkg.name()) + .replace("{version}", &dep.unit.pkg.version().to_string()); + rustdoc.arg("--extern-html-root-url"); + rustdoc.arg(format!("{}={}", dep.unit.target.crate_name(), url)); + *unstable_opts = true; + } + } + build_all_urls( + build_runner, + rustdoc, + &dep.unit, + name2url, + map, + unstable_opts, + seen, + ); + } +} + +/// Adds unstable flag [`--extern-html-root-url`][1] to the given `rustdoc` +/// invocation. This is for unstable feature [`-Zrustdoc-map`][2]. +/// +/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#--extern-html-root-url-control-how-rustdoc-links-to-non-local-crates +/// [2]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#rustdoc-map +pub fn add_root_urls( + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + rustdoc: &mut ProcessBuilder, +) -> CargoResult<()> { + let gctx = build_runner.bcx.gctx; + if !gctx.cli_unstable().rustdoc_map { + tracing::debug!("`doc.extern-map` ignored, requires -Zrustdoc-map flag"); + return Ok(()); + } + let map = gctx.doc_extern_map()?; + let mut unstable_opts = false; + // Collect mapping of registry name -> index url. + let name2url: HashMap<&String, Url> = map + .registries + .keys() + .filter_map(|name| { + if let Ok(index_url) = gctx.get_registry_index(name) { + Some((name, index_url)) + } else { + tracing::warn!( + "`doc.extern-map.{}` specifies a registry that is not defined", + name + ); + None + } + }) + .collect(); + build_all_urls( + build_runner, + rustdoc, + unit, + &name2url, + map, + &mut unstable_opts, + &mut HashSet::new(), + ); + let std_url = match &map.std { + None | Some(RustdocExternMode::Remote) => None, + Some(RustdocExternMode::Local) => { + let sysroot = &build_runner.bcx.target_data.info(CompileKind::Host).sysroot; + let html_root = sysroot.join("share").join("doc").join("rust").join("html"); + if html_root.exists() { + let url = Url::from_file_path(&html_root).map_err(|()| { + internal(format!( + "`{}` failed to convert to URL", + html_root.display() + )) + })?; + Some(url.to_string()) + } else { + tracing::warn!( + "`doc.extern-map.std` is \"local\", but local docs don't appear to exist at {}", + html_root.display() + ); + None + } + } + Some(RustdocExternMode::Url(s)) => Some(s.to_string()), + }; + if let Some(url) = std_url { + for name in &["std", "core", "alloc", "proc_macro"] { + rustdoc.arg("--extern-html-root-url"); + rustdoc.arg(format!("{}={}", name, url)); + unstable_opts = true; + } + } + + if unstable_opts { + rustdoc.arg("-Zunstable-options"); + } + Ok(()) +} + +/// Adds unstable flag [`--output-format`][1] to the given `rustdoc` +/// invocation. This is for unstable feature [`-Zunstable-features`]. +/// +/// [1]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html?highlight=output-format#-w--output-format-output-format +pub fn add_output_format( + build_runner: &BuildRunner<'_, '_>, + unit: &Unit, + rustdoc: &mut ProcessBuilder, +) -> CargoResult<()> { + let gctx = build_runner.bcx.gctx; + if !gctx.cli_unstable().unstable_options { + tracing::debug!("`unstable-options` is ignored, required -Zunstable-options flag"); + return Ok(()); + } + + if let CompileMode::Doc { json: true, .. } = unit.mode { + rustdoc.arg("-Zunstable-options"); + rustdoc.arg("--output-format=json"); + } + + Ok(()) +} + +/// Indicates whether a target should have examples scraped from it by rustdoc. +/// Configured within Cargo.toml and only for unstable feature +/// [`-Zrustdoc-scrape-examples`][1]. +/// +/// [1]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#scrape-examples +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy)] +pub enum RustdocScrapeExamples { + Enabled, + Disabled, + Unset, +} + +impl RustdocScrapeExamples { + pub fn is_enabled(&self) -> bool { + matches!(self, RustdocScrapeExamples::Enabled) + } + + pub fn is_unset(&self) -> bool { + matches!(self, RustdocScrapeExamples::Unset) + } +} + +impl BuildContext<'_, '_> { + /// Returns the set of [`Docscrape`] units that have a direct dependency on `unit`. + /// + /// [`RunCustomBuild`] units are excluded because we allow failures + /// from type checks but not build script executions. + /// A plain old `cargo doc` would just die if a build script execution fails, + /// there is no reason for `-Zrustdoc-scrape-examples` to keep going. + /// + /// [`Docscrape`]: crate::core::compiler::CompileMode::Docscrape + /// [`RunCustomBuild`]: crate::core::compiler::CompileMode::Docscrape + pub fn scrape_units_have_dep_on<'a>(&'a self, unit: &'a Unit) -> Vec<&'a Unit> { + self.scrape_units + .iter() + .filter(|scrape_unit| { + self.unit_graph[scrape_unit] + .iter() + .any(|dep| &dep.unit == unit && !dep.unit.mode.is_run_custom_build()) + }) + .collect() + } + + /// Returns true if this unit is needed for doing doc-scraping and is also + /// allowed to fail without killing the build. + pub fn unit_can_fail_for_docscraping(&self, unit: &Unit) -> bool { + // If the unit is not a Docscrape unit, e.g. a Lib target that is + // checked to scrape an Example target, then we need to get the doc-scrape-examples + // configuration for the reverse-dependent Example target. + let for_scrape_units = if unit.mode.is_doc_scrape() { + vec![unit] + } else { + self.scrape_units_have_dep_on(unit) + }; + + if for_scrape_units.is_empty() { + false + } else { + // All Docscrape units must have doc-scrape-examples unset. If any are true, + // then the unit is not allowed to fail. + for_scrape_units + .iter() + .all(|unit| unit.target.doc_scrape_examples().is_unset()) + } + } +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/standard_lib.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/standard_lib.rs new file mode 100644 index 000000000..18253b5d4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/standard_lib.rs @@ -0,0 +1,250 @@ +//! Code for building the standard library. + +use crate::core::compiler::unit_dependencies::IsArtifact; +use crate::core::compiler::UnitInterner; +use crate::core::compiler::{CompileKind, CompileMode, RustcTargetData, Unit}; +use crate::core::profiles::{Profiles, UnitFor}; +use crate::core::resolver::features::{CliFeatures, FeaturesFor, ResolvedFeatures}; +use crate::core::resolver::HasDevUnits; +use crate::core::{PackageId, PackageSet, Resolve, Workspace}; +use crate::ops::{self, Packages}; +use crate::util::errors::CargoResult; + +use std::collections::{HashMap, HashSet}; +use std::path::PathBuf; + +use super::BuildConfig; + +fn std_crates<'a>(crates: &'a [String], default: &'static str, units: &[Unit]) -> HashSet<&'a str> { + let mut crates = HashSet::from_iter(crates.iter().map(|s| s.as_str())); + // This is a temporary hack until there is a more principled way to + // declare dependencies in Cargo.toml. + if crates.is_empty() { + crates.insert(default); + } + if crates.contains("std") { + crates.insert("core"); + crates.insert("alloc"); + crates.insert("proc_macro"); + crates.insert("panic_unwind"); + crates.insert("compiler_builtins"); + // Only build libtest if it looks like it is needed (libtest depends on libstd) + // If we know what units we're building, we can filter for libtest depending on the jobs. + if units + .iter() + .any(|unit| unit.mode.is_rustc_test() && unit.target.harness()) + { + crates.insert("test"); + } + } else if crates.contains("core") { + crates.insert("compiler_builtins"); + } + + crates +} + +/// Resolve the standard library dependencies. +/// +/// * `crates` is the arg value from `-Zbuild-std`. +pub fn resolve_std<'gctx>( + ws: &Workspace<'gctx>, + target_data: &mut RustcTargetData<'gctx>, + build_config: &BuildConfig, + crates: &[String], + kinds: &[CompileKind], +) -> CargoResult<(PackageSet<'gctx>, Resolve, ResolvedFeatures)> { + if build_config.build_plan { + ws.gctx() + .shell() + .warn("-Zbuild-std does not currently fully support --build-plan")?; + } + + let src_path = detect_sysroot_src_path(target_data)?; + let std_ws_manifest_path = src_path.join("Cargo.toml"); + let gctx = ws.gctx(); + // TODO: Consider doing something to enforce --locked? Or to prevent the + // lock file from being written, such as setting ephemeral. + let mut std_ws = Workspace::new(&std_ws_manifest_path, gctx)?; + // Don't require optional dependencies in this workspace, aka std's own + // `[dev-dependencies]`. No need for us to generate a `Resolve` which has + // those included because we'll never use them anyway. + std_ws.set_require_optional_deps(false); + let specs = { + // If there is anything looks like needing std, resolve with it. + // If not, we assume only `core` maye be needed, as `core the most fundamental crate. + // + // This may need a UI overhaul if `build-std` wants to fully support multi-targets. + let maybe_std = kinds + .iter() + .any(|kind| target_data.info(*kind).maybe_support_std()); + let mut crates = std_crates(crates, if maybe_std { "std" } else { "core" }, &[]); + // `sysroot` is not in the default set because it is optional, but it needs + // to be part of the resolve in case we do need it or `libtest`. + crates.insert("sysroot"); + let specs = Packages::Packages(crates.into_iter().map(Into::into).collect()); + specs.to_package_id_specs(&std_ws)? + }; + let features = match &gctx.cli_unstable().build_std_features { + Some(list) => list.clone(), + None => vec![ + "panic-unwind".to_string(), + "backtrace".to_string(), + "default".to_string(), + ], + }; + 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, + &build_config.requested_kinds, + &cli_features, + &specs, + HasDevUnits::No, + crate::core::resolver::features::ForceAllTargets::No, + dry_run, + )?; + Ok(( + resolve.pkg_set, + resolve.targeted_resolve, + resolve.resolved_features, + )) +} + +/// Generates a map of root units for the standard library for each kind requested. +/// +/// * `crates` is the arg value from `-Zbuild-std`. +/// * `units` is the root units of the build. +pub fn generate_std_roots( + crates: &[String], + units: &[Unit], + std_resolve: &Resolve, + std_features: &ResolvedFeatures, + kinds: &[CompileKind], + package_set: &PackageSet<'_>, + interner: &UnitInterner, + profiles: &Profiles, + target_data: &RustcTargetData<'_>, +) -> CargoResult>> { + // Generate a map of Units for each kind requested. + let mut ret = HashMap::new(); + let (maybe_std, maybe_core): (Vec<&CompileKind>, Vec<_>) = kinds + .iter() + .partition(|kind| target_data.info(**kind).maybe_support_std()); + for (default_crate, kinds) in [("core", maybe_core), ("std", maybe_std)] { + if kinds.is_empty() { + continue; + } + generate_roots( + &mut ret, + default_crate, + crates, + units, + std_resolve, + std_features, + &kinds, + package_set, + interner, + profiles, + target_data, + )?; + } + + Ok(ret) +} + +fn generate_roots( + ret: &mut HashMap>, + default: &'static str, + crates: &[String], + units: &[Unit], + std_resolve: &Resolve, + std_features: &ResolvedFeatures, + kinds: &[&CompileKind], + package_set: &PackageSet<'_>, + interner: &UnitInterner, + profiles: &Profiles, + target_data: &RustcTargetData<'_>, +) -> CargoResult<()> { + let std_ids = std_crates(crates, default, units) + .iter() + .map(|crate_name| std_resolve.query(crate_name)) + .collect::>>()?; + let std_pkgs = package_set.get_many(std_ids)?; + + for pkg in std_pkgs { + let lib = pkg + .targets() + .iter() + .find(|t| t.is_lib()) + .expect("std has a lib"); + // I don't think we need to bother with Check here, the difference + // in time is minimal, and the difference in caching is + // significant. + let mode = CompileMode::Build; + let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev); + for kind in kinds { + let kind = **kind; + let list = ret.entry(kind).or_insert_with(Vec::new); + let unit_for = UnitFor::new_normal(kind); + let profile = profiles.get_profile( + pkg.package_id(), + /*is_member*/ false, + /*is_local*/ false, + unit_for, + kind, + ); + list.push(interner.intern( + pkg, + lib, + profile, + kind, + mode, + features.clone(), + target_data.info(kind).rustflags.clone(), + target_data.info(kind).rustdocflags.clone(), + target_data.target_config(kind).links_overrides.clone(), + /*is_std*/ true, + /*dep_hash*/ 0, + IsArtifact::No, + None, + )); + } + } + Ok(()) +} + +fn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult { + if let Some(s) = target_data.gctx.get_env_os("__CARGO_TESTS_ONLY_SRC_ROOT") { + return Ok(s.into()); + } + + // NOTE: This is temporary until we figure out how to acquire the source. + let src_path = target_data + .info(CompileKind::Host) + .sysroot + .join("lib") + .join("rustlib") + .join("src") + .join("rust") + .join("library"); + let lock = src_path.join("Cargo.lock"); + if !lock.exists() { + let msg = format!( + "{:?} does not exist, unable to build with the standard \ + library, try:\n rustup component add rust-src", + lock + ); + match target_data.gctx.get_env("RUSTUP_TOOLCHAIN") { + Ok(rustup_toolchain) => { + anyhow::bail!("{} --toolchain {}", msg, rustup_toolchain); + } + Err(_) => { + anyhow::bail!(msg); + } + } + } + Ok(src_path) +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.js b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.js new file mode 100644 index 000000000..d9a0b53bd --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.js @@ -0,0 +1,495 @@ +// Position of the vertical axis. +const X_LINE = 50; +// General-use margin size. +const MARGIN = 5; +// Position of the horizontal axis, relative to the bottom. +const Y_LINE = 35; +// Minimum distance between time tick labels. +const MIN_TICK_DIST = 50; +// Radius for rounded rectangle corners. +const RADIUS = 3; +// Height of unit boxes. +const BOX_HEIGHT = 25; +// Distance between Y tick marks on the unit graph. +const Y_TICK_DIST = BOX_HEIGHT + 2; +// Rects used for mouseover detection. +// Objects of {x, y, x2, y2, i} where `i` is the index into UNIT_DATA. +let HIT_BOXES = []; +// Index into UNIT_DATA of the last unit hovered over by mouse. +let LAST_HOVER = null; +// Key is unit index, value is {x, y, width, rmeta_x} of the box. +let UNIT_COORDS = {}; +// Map of unit index to the index it was unlocked by. +let REVERSE_UNIT_DEPS = {}; +let REVERSE_UNIT_RMETA_DEPS = {}; + +// Colors from css +const getCssColor = name => getComputedStyle(document.body).getPropertyValue(name); +const TEXT_COLOR = getCssColor('--text'); +const BG_COLOR = getCssColor('--background'); +const CANVAS_BG = getCssColor('--canvas-background'); +const AXES_COLOR = getCssColor('--canvas-axes'); +const GRID_COLOR = getCssColor('--canvas-grid'); +const BLOCK_COLOR = getCssColor('--canvas-block'); +const CUSTOM_BUILD_COLOR = getCssColor('--canvas-custom-build'); +const NOT_CUSTOM_BUILD_COLOR = getCssColor('--canvas-not-custom-build'); +const DEP_LINE_COLOR = getCssColor('--canvas-dep-line'); +const DEP_LINE_HIGHLIGHTED_COLOR = getCssColor('--canvas-dep-line-highlighted'); +const CPU_COLOR = getCssColor('--canvas-cpu'); + +for (let n=0; n unit.duration >= min_time); + + const graph_height = Y_TICK_DIST * units.length; + const {ctx, graph_width, canvas_width, canvas_height, px_per_sec} = draw_graph_axes('pipeline-graph', graph_height); + const container = document.getElementById('pipeline-container'); + container.style.width = canvas_width; + container.style.height = canvas_height; + + // Canvas for hover highlights. This is a separate layer to improve performance. + const linectx = setup_canvas('pipeline-graph-lines', canvas_width, canvas_height); + linectx.clearRect(0, 0, canvas_width, canvas_height); + ctx.strokeStyle = AXES_COLOR; + // Draw Y tick marks. + for (let n=1; n 1 ? `${unit.name} (v${unit.version})${unit.target}` : `${unit.name}${unit.target}`; + const label = `${labelName}: ${unit.duration}s`; + + const text_info = ctx.measureText(label); + const label_x = Math.min(x + 5.0, canvas_width - text_info.width - X_LINE); + ctx.fillText(label, label_x, y + BOX_HEIGHT / 2); + draw_dep_lines(ctx, unit.i, false); + } + ctx.restore(); +} + +// Draws lines from the given unit to the units it unlocks. +function draw_dep_lines(ctx, unit_idx, highlighted) { + const unit = UNIT_DATA[unit_idx]; + const {x, y, rmeta_x} = UNIT_COORDS[unit_idx]; + ctx.save(); + for (const unlocked of unit.unlocked_units) { + draw_one_dep_line(ctx, x, y, unlocked, highlighted); + } + for (const unlocked of unit.unlocked_rmeta_units) { + draw_one_dep_line(ctx, rmeta_x, y, unlocked, highlighted); + } + ctx.restore(); +} + +function draw_one_dep_line(ctx, from_x, from_y, to_unit, highlighted) { + if (to_unit in UNIT_COORDS) { + let {x: u_x, y: u_y} = UNIT_COORDS[to_unit]; + ctx.strokeStyle = highlighted ? DEP_LINE_HIGHLIGHTED_COLOR: DEP_LINE_COLOR; + ctx.setLineDash([2]); + ctx.beginPath(); + ctx.moveTo(from_x, from_y+BOX_HEIGHT/2); + ctx.lineTo(from_x-5, from_y+BOX_HEIGHT/2); + ctx.lineTo(from_x-5, u_y+BOX_HEIGHT/2); + ctx.lineTo(u_x, u_y+BOX_HEIGHT/2); + ctx.stroke(); + } +} + +function render_timing_graph() { + if (CONCURRENCY_DATA.length == 0) { + return; + } + const HEIGHT = 400; + const AXIS_HEIGHT = HEIGHT - MARGIN - Y_LINE; + const TOP_MARGIN = 10; + const GRAPH_HEIGHT = AXIS_HEIGHT - TOP_MARGIN; + + const {canvas_width, graph_width, ctx} = draw_graph_axes('timing-graph', AXIS_HEIGHT); + + // Draw Y tick marks and labels. + let max_v = 0; + for (c of CONCURRENCY_DATA) { + max_v = Math.max(max_v, c.active, c.waiting, c.inactive); + } + const px_per_v = GRAPH_HEIGHT / max_v; + const {step, tick_dist, num_ticks} = split_ticks(max_v, px_per_v, GRAPH_HEIGHT); + ctx.textAlign = 'end'; + for (n=0; n 1) { + ctx.beginPath(); + ctx.fillStyle = cpuFillStyle; + let bottomLeft = coord(CPU_USAGE[0][0], 0); + ctx.moveTo(bottomLeft.x, bottomLeft.y); + for (let i=0; i < CPU_USAGE.length; i++) { + let [time, usage] = CPU_USAGE[i]; + let {x, y} = coord(time, usage / 100.0 * max_v); + ctx.lineTo(x, y); + } + let bottomRight = coord(CPU_USAGE[CPU_USAGE.length - 1][0], 0); + ctx.lineTo(bottomRight.x, bottomRight.y); + ctx.fill(); + } + + function draw_line(style, key) { + let first = CONCURRENCY_DATA[0]; + let last = coord(first.t, key(first)); + ctx.strokeStyle = style; + ctx.beginPath(); + ctx.moveTo(last.x, last.y); + for (let i=1; i 100) { + throw Error("tick loop too long"); + } + count += 1; + if (max_value <= max_ticks * step) { + break; + } + step += 10; + } + } + const tick_dist = px_per_v * step; + const num_ticks = Math.floor(max_value / step); + return {step, tick_dist, num_ticks}; +} + +function codegen_time(unit) { + if (unit.rmeta_time == null) { + return null; + } + let ctime = unit.duration - unit.rmeta_time; + return [unit.rmeta_time, ctime]; +} + +function roundedRect(ctx, x, y, width, height, r) { + r = Math.min(r, width, height); + ctx.beginPath(); + ctx.moveTo(x+r, y); + ctx.lineTo(x+width-r, y); + ctx.arc(x+width-r, y+r, r, 3*Math.PI/2, 0); + ctx.lineTo(x+width, y+height-r); + ctx.arc(x+width-r, y+height-r, r, 0, Math.PI/2); + ctx.lineTo(x+r, y+height); + ctx.arc(x+r, y+height-r, r, Math.PI/2, Math.PI); + ctx.lineTo(x, y-r); + ctx.arc(x+r, y+r, r, Math.PI, 3*Math.PI/2); + ctx.closePath(); +} + +function pipeline_mouse_hit(event) { + // This brute-force method can be optimized if needed. + for (let box of HIT_BOXES) { + if (event.offsetX >= box.x && event.offsetX <= box.x2 && + event.offsetY >= box.y && event.offsetY <= box.y2) { + return box; + } + } +} + +function pipeline_mousemove(event) { + // Highlight dependency lines on mouse hover. + let box = pipeline_mouse_hit(event); + if (box) { + if (box.i != LAST_HOVER) { + LAST_HOVER = box.i; + let g = document.getElementById('pipeline-graph-lines'); + let ctx = g.getContext('2d'); + ctx.clearRect(0, 0, g.width, g.height); + ctx.save(); + ctx.translate(X_LINE, MARGIN); + ctx.lineWidth = 2; + draw_dep_lines(ctx, box.i, true); + + if (box.i in REVERSE_UNIT_DEPS) { + const dep_unit = REVERSE_UNIT_DEPS[box.i]; + if (dep_unit in UNIT_COORDS) { + const {x, y, rmeta_x} = UNIT_COORDS[dep_unit]; + draw_one_dep_line(ctx, x, y, box.i, true); + } + } + if (box.i in REVERSE_UNIT_RMETA_DEPS) { + const dep_unit = REVERSE_UNIT_RMETA_DEPS[box.i]; + if (dep_unit in UNIT_COORDS) { + const {x, y, rmeta_x} = UNIT_COORDS[dep_unit]; + draw_one_dep_line(ctx, rmeta_x, y, box.i, true); + } + } + ctx.restore(); + } + } +} + +render_pipeline_graph(); +render_timing_graph(); + +// Set up and handle controls. +{ + const range = document.getElementById('min-unit-time'); + const time_output = document.getElementById('min-unit-time-output'); + time_output.innerHTML = `${range.value}s`; + range.oninput = event => { + time_output.innerHTML = `${range.value}s`; + render_pipeline_graph(); + }; + + const scale = document.getElementById('scale'); + const scale_output = document.getElementById('scale-output'); + scale_output.innerHTML = `${scale.value}`; + scale.oninput = event => { + scale_output.innerHTML = `${scale.value}`; + render_pipeline_graph(); + render_timing_graph(); + }; +} diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.rs b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.rs new file mode 100644 index 000000000..ec6e7741e --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/cargo/core/compiler/timings.rs @@ -0,0 +1,799 @@ +//! Timing tracking. +//! +//! This module implements some simple tracking information for timing of how +//! long it takes for different units to compile. +use super::{CompileMode, Unit}; +use crate::core::compiler::job_queue::JobId; +use crate::core::compiler::{BuildContext, BuildRunner, 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, GlobalContext}; +use anyhow::Context as _; +use cargo_util::paths; +use std::collections::HashMap; +use std::io::{BufWriter, Write}; +use std::thread::available_parallelism; +use std::time::{Duration, Instant, SystemTime}; + +/// Tracking information for the entire build. +/// +/// Methods on this structure are generally called from the main thread of a +/// running [`JobQueue`] instance (`DrainState` in specific) when the queue +/// receives messages from spawned off threads. +/// +/// [`JobQueue`]: super::JobQueue +pub struct Timings<'gctx> { + gctx: &'gctx GlobalContext, + /// Whether or not timings should be captured. + enabled: bool, + /// If true, saves an HTML report to disk. + report_html: bool, + /// If true, emits JSON information with timing information. + report_json: bool, + /// When Cargo started. + start: Instant, + /// A rendered string of when compilation started. + start_str: String, + /// A summary of the root units. + /// + /// Tuples of `(package_description, target_descriptions)`. + root_targets: Vec<(String, Vec)>, + /// The build profile. + profile: String, + /// Total number of fresh units. + total_fresh: u32, + /// Total number of dirty units. + total_dirty: u32, + /// Time tracking for each individual unit. + unit_times: Vec, + /// Units that are in the process of being built. + /// When they finished, they are moved to `unit_times`. + active: HashMap, + /// Concurrency-tracking information. This is periodically updated while + /// compilation progresses. + concurrency: Vec, + /// Last recorded state of the system's CPUs and when it happened + last_cpu_state: Option, + last_cpu_recording: Instant, + /// Recorded CPU states, stored as tuples. First element is when the + /// recording was taken and second element is percentage usage of the + /// system. + cpu_usage: Vec<(f64, f64)>, +} + +/// Tracking information for an individual unit. +struct UnitTime { + unit: Unit, + /// A string describing the cargo target. + target: String, + /// The time when this unit started as an offset in seconds from `Timings::start`. + start: f64, + /// Total time to build this unit in seconds. + duration: f64, + /// The time when the `.rmeta` file was generated, an offset in seconds + /// from `start`. + rmeta_time: Option, + /// Reverse deps that are freed to run after this unit finished. + unlocked_units: Vec, + /// Same as `unlocked_units`, but unlocked by rmeta. + unlocked_rmeta_units: Vec, +} + +/// Periodic concurrency tracking information. +#[derive(serde::Serialize)] +struct Concurrency { + /// Time as an offset in seconds from `Timings::start`. + t: f64, + /// Number of units currently running. + active: usize, + /// Number of units that could run, but are waiting for a jobserver token. + waiting: usize, + /// Number of units that are not yet ready, because they are waiting for + /// dependencies to finish. + inactive: usize, +} + +impl<'gctx> Timings<'gctx> { + pub fn new(bcx: &BuildContext<'_, 'gctx>, root_units: &[Unit]) -> Timings<'gctx> { + let has_report = |what| bcx.build_config.timing_outputs.contains(&what); + let report_html = has_report(TimingOutput::Html); + let report_json = has_report(TimingOutput::Json); + let enabled = report_html | report_json; + + let mut root_map: HashMap> = HashMap::new(); + for unit in root_units { + let target_desc = unit.target.description_named(); + root_map + .entry(unit.pkg.package_id()) + .or_default() + .push(target_desc); + } + let root_targets = root_map + .into_iter() + .map(|(pkg_id, targets)| { + let pkg_desc = format!("{} {}", pkg_id.name(), pkg_id.version()); + (pkg_desc, targets) + }) + .collect(); + let start_str = humantime::format_rfc3339_seconds(SystemTime::now()).to_string(); + let profile = bcx.build_config.requested_profile.to_string(); + let last_cpu_state = if enabled { + match State::current() { + Ok(state) => Some(state), + Err(e) => { + tracing::info!("failed to get CPU state, CPU tracking disabled: {:?}", e); + None + } + } + } else { + None + }; + + Timings { + gctx: bcx.gctx, + enabled, + report_html, + report_json, + start: bcx.gctx.creation_time(), + start_str, + root_targets, + profile, + total_fresh: 0, + total_dirty: 0, + unit_times: Vec::new(), + active: HashMap::new(), + concurrency: Vec::new(), + last_cpu_state, + last_cpu_recording: Instant::now(), + cpu_usage: Vec::new(), + } + } + + /// Mark that a unit has started running. + pub fn unit_start(&mut self, id: JobId, unit: Unit) { + if !self.enabled { + return; + } + let mut target = if unit.target.is_lib() && unit.mode == CompileMode::Build { + // Special case for brevity, since most dependencies hit + // this path. + "".to_string() + } else { + format!(" {}", unit.target.description_named()) + }; + match unit.mode { + CompileMode::Test => target.push_str(" (test)"), + CompileMode::Build => {} + CompileMode::Check { test: true } => target.push_str(" (check-test)"), + CompileMode::Check { test: false } => target.push_str(" (check)"), + CompileMode::Bench => target.push_str(" (bench)"), + CompileMode::Doc { .. } => target.push_str(" (doc)"), + CompileMode::Doctest => target.push_str(" (doc test)"), + CompileMode::Docscrape => target.push_str(" (doc scrape)"), + CompileMode::RunCustomBuild => target.push_str(" (run)"), + } + let unit_time = UnitTime { + unit, + target, + start: self.start.elapsed().as_secs_f64(), + duration: 0.0, + rmeta_time: None, + unlocked_units: Vec::new(), + unlocked_rmeta_units: Vec::new(), + }; + assert!(self.active.insert(id, unit_time).is_none()); + } + + /// Mark that the `.rmeta` file as generated. + pub fn unit_rmeta_finished(&mut self, id: JobId, unlocked: Vec<&Unit>) { + if !self.enabled { + return; + } + // `id` may not always be active. "fresh" units unconditionally + // generate `Message::Finish`, but this active map only tracks dirty + // units. + 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); + assert!(unit_time.unlocked_rmeta_units.is_empty()); + unit_time + .unlocked_rmeta_units + .extend(unlocked.iter().cloned().cloned()); + } + + /// Mark that a unit has finished running. + pub fn unit_finished(&mut self, id: JobId, unlocked: Vec<&Unit>) { + if !self.enabled { + return; + } + // See note above in `unit_rmeta_finished`, this may not always be active. + 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; + assert!(unit_time.unlocked_units.is_empty()); + unit_time + .unlocked_units + .extend(unlocked.iter().cloned().cloned()); + if self.report_json { + let msg = machine_message::TimingInfo { + package_id: unit_time.unit.pkg.package_id().to_spec(), + target: &unit_time.unit.target, + mode: unit_time.unit.mode, + duration: unit_time.duration, + rmeta_time: unit_time.rmeta_time, + } + .to_json_string(); + crate::drop_println!(self.gctx, "{}", msg); + } + self.unit_times.push(unit_time); + } + + /// This is called periodically to mark the concurrency of internal structures. + pub fn mark_concurrency(&mut self, active: usize, waiting: usize, inactive: usize) { + if !self.enabled { + return; + } + let c = Concurrency { + t: self.start.elapsed().as_secs_f64(), + active, + waiting, + inactive, + }; + self.concurrency.push(c); + } + + /// Mark that a fresh unit was encountered. (No re-compile needed) + pub fn add_fresh(&mut self) { + self.total_fresh += 1; + } + + /// Mark that a dirty unit was encountered. (Re-compile needed) + pub fn add_dirty(&mut self) { + self.total_dirty += 1; + } + + /// Take a sample of CPU usage + pub fn record_cpu(&mut self) { + if !self.enabled { + return; + } + let Some(prev) = &mut self.last_cpu_state else { + return; + }; + // Don't take samples too frequently, even if requested. + let now = Instant::now(); + if self.last_cpu_recording.elapsed() < Duration::from_millis(100) { + return; + } + let current = match State::current() { + Ok(s) => s, + Err(e) => { + tracing::info!("failed to get CPU state: {:?}", e); + return; + } + }; + let pct_idle = current.idle_since(prev); + *prev = current; + self.last_cpu_recording = now; + let dur = now.duration_since(self.start).as_secs_f64(); + self.cpu_usage.push((dur, 100.0 - pct_idle)); + } + + /// Call this when all units are finished. + pub fn finished( + &mut self, + build_runner: &BuildRunner<'_, '_>, + error: &Option, + ) -> CargoResult<()> { + if !self.enabled { + return Ok(()); + } + self.mark_concurrency(0, 0, 0); + self.unit_times + .sort_unstable_by(|a, b| a.start.partial_cmp(&b.start).unwrap()); + if self.report_html { + self.report_html(build_runner, error) + .context("failed to save timing report")?; + } + Ok(()) + } + + /// Save HTML report to disk. + fn report_html( + &self, + build_runner: &BuildRunner<'_, '_>, + error: &Option, + ) -> CargoResult<()> { + let duration = self.start.elapsed().as_secs_f64(); + let timestamp = self.start_str.replace(&['-', ':'][..], ""); + let timings_path = build_runner.files().host_root().join("cargo-timings"); + paths::create_dir_all(&timings_path)?; + let filename = timings_path.join(format!("cargo-timing-{}.html", timestamp)); + let mut f = BufWriter::new(paths::create(&filename)?); + let roots: Vec<&str> = self + .root_targets + .iter() + .map(|(name, _targets)| name.as_str()) + .collect(); + f.write_all(HTML_TMPL.replace("{ROOTS}", &roots.join(", ")).as_bytes())?; + self.write_summary_table(&mut f, duration, build_runner.bcx, error)?; + f.write_all(HTML_CANVAS.as_bytes())?; + self.write_unit_table(&mut f)?; + // It helps with pixel alignment to use whole numbers. + writeln!( + f, + "\n\ + \n\ + \n\ + ", + include_str!("timings.js") + )?; + drop(f); + + let unstamped_filename = timings_path.join("cargo-timing.html"); + paths::link_or_copy(&filename, &unstamped_filename)?; + + let mut shell = self.gctx.shell(); + let timing_path = std::env::current_dir().unwrap_or_default().join(&filename); + let link = shell.err_file_hyperlink(&timing_path); + let msg = format!("report saved to {link}{}{link:#}", timing_path.display(),); + shell.status_with_color("Timing", msg, &style::NOTE)?; + + Ok(()) + } + + /// Render the summary table. + fn write_summary_table( + &self, + f: &mut impl Write, + duration: f64, + bcx: &BuildContext<'_, '_>, + error: &Option, + ) -> CargoResult<()> { + let targets: Vec = self + .root_targets + .iter() + .map(|(name, targets)| format!("{} ({})", name, targets.join(", "))) + .collect(); + let targets = targets.join("
"); + let time_human = if duration > 60.0 { + format!(" ({}m {:.1}s)", duration as u32 / 60, duration % 60.0) + } else { + "".to_string() + }; + let total_time = format!("{:.1}s{}", duration, time_human); + let max_concurrency = self.concurrency.iter().map(|c| c.active).max().unwrap(); + let num_cpus = available_parallelism() + .map(|x| x.get().to_string()) + .unwrap_or_else(|_| "n/a".into()); + let rustc_info = render_rustc_info(bcx); + let error_msg = match error { + Some(e) => format!(r#"Error:{e}"#), + None => "".to_string(), + }; + write!( + f, + r#" + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{} +
Targets:{}
Profile:{}
Fresh units:{}
Dirty units:{}
Total units:{}
Max concurrency:{} (jobs={} ncpu={})
Build start:{}
Total time:{}
rustc:{}
+"#, + targets, + self.profile, + self.total_fresh, + self.total_dirty, + self.total_fresh + self.total_dirty, + max_concurrency, + bcx.jobs(), + num_cpus, + self.start_str, + total_time, + rustc_info, + error_msg, + )?; + Ok(()) + } + + /// Write timing data in JavaScript. Primarily for `timings.js` to put data + /// in a ` diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/overriding-dependencies.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/overriding-dependencies.md new file mode 100644 index 000000000..6d80df198 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/overriding-dependencies.md @@ -0,0 +1,359 @@ +# 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 +it's been published to [crates.io]. For example: + +* A crate you're working on is also used in a much larger application you're + working on, and you'd like to test a bug fix to the library inside of the + larger application. +* An upstream crate you don't work on has a new feature or a bug fix on the + master branch of its git repository which you'd like to test out. +* You're about to publish a new major version of your crate, but you'd like to + do integration testing across an entire package to ensure the new major + version works. +* You've submitted a fix to an upstream crate for a bug you found, but you'd + like to immediately have your application start depending on the fixed + version of the crate to avoid blocking on the bug fix getting merged. + +These scenarios can be solved with the [`[patch]` manifest +section](#the-patch-section). + +This chapter walks through a few different use cases, and includes details +on the different ways to override a dependency. + +* Example use cases + * [Testing a bugfix](#testing-a-bugfix) + * [Working with an unpublished minor version](#working-with-an-unpublished-minor-version) + * [Overriding repository URL](#overriding-repository-url) + * [Prepublishing a breaking change](#prepublishing-a-breaking-change) + * [Using `[patch]` with multiple versions](#using-patch-with-multiple-versions) +* Reference + * [The `[patch]` section](#the-patch-section) + * [The `[replace]` section](#the-replace-section) + * [`paths` overrides](#paths-overrides) + +> **Note**: See also specifying a dependency with [multiple locations], which +> can be used to override the source for a single dependency declaration in a +> local package. + +## 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 +try to fix the bug! Originally your manifest will look like: + +[`uuid` crate]: https://crates.io/crates/uuid + +```toml +[package] +name = "my-library" +version = "0.1.0" + +[dependencies] +uuid = "1.0" +``` + +First thing we'll do is to clone the [`uuid` repository][uuid-repository] +locally via: + +```console +$ git clone https://github.com/uuid-rs/uuid.git +``` + +Next we'll edit the manifest of `my-library` to contain: + +```toml +[patch.crates-io] +uuid = { path = "../path/to/uuid" } +``` + +Here we declare that we're *patching* the source `crates-io` with a new +dependency. This will effectively add the local checked out version of `uuid` to +the crates.io registry for our local package. + +Next up we need to ensure that our lock file is updated to use this new version +of `uuid` so our package uses the locally checked out copy instead of one from +crates.io. The way `[patch]` works is that it'll load the dependency at +`../path/to/uuid` and then whenever crates.io is queried for versions of `uuid` +it'll *also* return the local version. + +This means that the version number of the local checkout is significant and will +affect whether the patch is used. Our manifest declared `uuid = "1.0"` which +means we'll only resolve to `>= 1.0.0, < 2.0.0`, and Cargo's greedy resolution +algorithm also means that we'll resolve to the maximum version within that +range. Typically this doesn't matter as the version of the git repository will +already be greater or match the maximum version published on crates.io, but it's +important to keep this in mind! + +In any case, typically all you need to do now is: + +```console +$ cargo build + Compiling uuid v1.0.0 (.../uuid) + Compiling my-library v0.1.0 (.../my-library) + Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs +``` + +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 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 +is to likely submit that as a pull request to the `uuid` crate itself. Once +you've done this then you can also update the `[patch]` section. The listing +inside of `[patch]` is just like the `[dependencies]` section, so once your pull +request is merged you could change your `path` dependency to: + +```toml +[patch.crates-io] +uuid = { git = 'https://github.com/uuid-rs/uuid.git' } +``` + +[uuid-repository]: https://github.com/uuid-rs/uuid + +## 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` +crate. You've implemented this feature, tested it locally above with `[patch]`, +and submitted a pull request. Let's go over how you continue to use and test it +before it's actually published. + +Let's also say that the current version of `uuid` on crates.io is `1.0.0`, but +since then the master branch of the git repository has updated to `1.0.1`. This +branch includes your new feature you submitted previously. To use this +repository we'll edit our `Cargo.toml` to look like + +```toml +[package] +name = "my-library" +version = "0.1.0" + +[dependencies] +uuid = "1.0.1" + +[patch.crates-io] +uuid = { git = 'https://github.com/uuid-rs/uuid.git' } +``` + +Note that our local dependency on `uuid` has been updated to `1.0.1` as it's +what we'll actually require once the crate is published. This version doesn't +exist on crates.io, though, so we provide it with the `[patch]` section of the +manifest. + +Now when our library is built it'll fetch `uuid` from the git repository and +resolve to 1.0.1 inside the repository instead of trying to download a version +from crates.io. Once 1.0.1 is published on crates.io the `[patch]` section can +be deleted. + +It's also worth noting that `[patch]` applies *transitively*. Let's say you use +`my-library` in a larger package, such as: + +```toml +[package] +name = "my-binary" +version = "0.1.0" + +[dependencies] +my-library = { git = 'https://example.com/git/my-library' } +uuid = "1.0" + +[patch.crates-io] +uuid = { git = 'https://github.com/uuid-rs/uuid.git' } +``` + +Remember that `[patch]` is applicable *transitively* but can only be defined at +the *top level* so we consumers of `my-library` have to repeat the `[patch]` section +if necessary. Here, though, the new `uuid` crate applies to *both* our dependency on +`uuid` and the `my-library -> uuid` dependency. The `uuid` crate will be resolved to +one version for this entire crate graph, 1.0.1, and it'll be pulled from the git +repository. + +### 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 +dependency is a git dependency, you can override it to a local path with: + +```toml +[patch."https://github.com/your/repository"] +my-library = { path = "../my-library/path" } +``` + +And that's it! + +## 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 +means that we're going to be creating version 2.0.0 of the `uuid` crate. After +we've submitted all changes upstream we can update our manifest for +`my-library` to look like: + +```toml +[dependencies] +uuid = "2.0" + +[patch.crates-io] +uuid = { git = "https://github.com/uuid-rs/uuid.git", branch = "2.0.0" } +``` + +And that's it! Like with the previous example the 2.0.0 version doesn't actually +exist on crates.io but we can still put it in through a git dependency through +the usage of the `[patch]` section. As a thought exercise let's take another +look at the `my-binary` manifest from above again as well: + +```toml +[package] +name = "my-binary" +version = "0.1.0" + +[dependencies] +my-library = { git = 'https://example.com/git/my-library' } +uuid = "1.0" + +[patch.crates-io] +uuid = { git = 'https://github.com/uuid-rs/uuid.git', branch = '2.0.0' } +``` + +Note that this will actually resolve to two versions of the `uuid` crate. The +`my-binary` crate will continue to use the 1.x.y series of the `uuid` crate but +the `my-library` crate will use the `2.0.0` version of `uuid`. This will allow you +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 + +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 +a bugfix that we'd like to use to its `1.*` series but we'd also like to +prototype using a `2.0.0` version of serde we have in our git repository. To +configure this we'd do: + +```toml +[patch.crates-io] +serde = { git = 'https://github.com/serde-rs/serde.git' } +serde2 = { git = 'https://github.com/example/serde.git', package = 'serde', branch = 'v2' } +``` + +The first `serde = ...` directive indicates that serde `1.*` should be used +from the git repository (pulling in the bugfix we need) and the second `serde2 += ...` directive indicates that the `serde` package should also be pulled from +the `v2` branch of `https://github.com/example/serde`. We're assuming here +that `Cargo.toml` on that branch mentions version `2.0.0`. + +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 of `Cargo.toml` can be used to override dependencies +with other copies. The syntax is similar to the +[`[dependencies]`][dependencies] section: + +```toml +[patch.crates-io] +foo = { git = 'https://github.com/example/foo.git' } +bar = { path = 'my/local/bar' } + +[dependencies.baz] +git = 'https://github.com/example/baz.git' + +[patch.'https://github.com/example/baz'] +baz = { git = 'https://github.com/example/patched-baz.git', branch = 'my-branch' } +``` + +> **Note**: The `[patch]` table can also be specified as a [configuration +> option](config.md), such as in a `.cargo/config.toml` file or a CLI option +> like `--config 'patch.crates-io.rand.path="rand"'`. This can be useful for +> local-only changes that you don't want to commit, or temporarily testing a +> patch. + +The `[patch]` table is made of dependency-like sub-tables. Each key after +`[patch]` is a URL of the source that is being patched, or the name of a +registry. The name `crates-io` may be used to override the default registry +[crates.io]. The first `[patch]` in the example above demonstrates overriding +[crates.io], and the second `[patch]` demonstrates overriding a git source. + +Each entry in these tables is a normal dependency specification, the same as +found in the `[dependencies]` section of the manifest. The dependencies listed +in the `[patch]` section are resolved and used to patch the source at the +URL specified. The above manifest snippet patches the `crates-io` source (e.g. +crates.io itself) with the `foo` crate and `bar` crate. It also +patches the `https://github.com/example/baz` source with a `my-branch` that +comes from elsewhere. + +Sources can be patched with versions of crates that do not exist, and they can +also be patched with versions of crates that already exist. If a source is +patched with a crate version that already exists in the source, then the +source's original crate is replaced. + +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 + +> **Note**: `[replace]` is deprecated. You should use the +> [`[patch]`](#the-patch-section) table instead. + +This section of Cargo.toml can be used to override dependencies with other +copies. The syntax is similar to the `[dependencies]` section: + +```toml +[replace] +"foo:0.1.0" = { git = 'https://github.com/example/foo.git' } +"bar:1.0.2" = { path = 'my/local/bar' } +``` + +Each key in the `[replace]` table is a [package ID +specification](pkgid-spec.md), which allows arbitrarily choosing a node in the +dependency graph to override (the 3-part version number is required). The +value of each key is the same as the `[dependencies]` syntax for specifying +dependencies, except that you can't specify features. Note that when a crate +is overridden the copy it's overridden with must have both the same name and +version, but it can come from a different source (e.g., git or a local path). + +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 + +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 +case Cargo offers a much more limited version of overrides called **path +overrides**. + +Path overrides are specified through [`.cargo/config.toml`](config.md) instead of +`Cargo.toml`. Inside of `.cargo/config.toml` you'll specify a key called `paths`: + +```toml +paths = ["/path/to/uuid"] +``` + +This array should be filled with directories that contain a `Cargo.toml`. In +this instance, we’re just adding `uuid`, so it will be the only one that’s +overridden. This path can be either absolute or relative to the directory that +contains the `.cargo` folder. + +Path overrides are more restricted than the `[patch]` section, however, in +that they cannot change the structure of the dependency graph. When a +path replacement is used then the previous set of dependencies +must all match exactly to the new `Cargo.toml` specification. For example this +means that path overrides cannot be used to test out adding a dependency to a +crate, instead `[patch]` must be used in that situation. As a result usage of a +path override is typically isolated to quick bug fixes rather than larger +changes. + +> **Note**: using a local configuration to override paths will only work for +> crates that have been published to [crates.io]. You cannot use this feature +> to tell Cargo how to find local unpublished crates. + + +[crates.io]: https://crates.io/ +[multiple locations]: specifying-dependencies.md#multiple-locations +[dependencies]: specifying-dependencies.md diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/pkgid-spec.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/pkgid-spec.md new file mode 100644 index 000000000..64d219c95 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/pkgid-spec.md @@ -0,0 +1,75 @@ +# 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. +To solve this problem, Cargo supports *Package ID Specifications*. A specification +is a string which is used to uniquely refer to one package within a graph of +packages. + +The specification may be fully qualified, such as +`https://github.com/rust-lang/crates.io-index#regex@1.4.3` or it may be +abbreviated, such as `regex`. The abbreviated form may be used as long as it +uniquely identifies a single package in the dependency graph. If there is +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 + +The formal grammar for a Package Id Specification is: + +```notrust +spec := pkgname | + [ kind "+" ] proto "://" hostname-and-path [ "?" query] [ "#" ( pkgname | semver ) ] +query = ( "branch" | "tag" | "rev" ) "=" ref +pkgname := name [ ("@" | ":" ) semver ] +semver := digits [ "." digits [ "." digits [ "-" prerelease ] [ "+" build ]]] + +kind = "registry" | "git" | "path" +proto := "http" | "git" | "file" | ... +``` + +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 + +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` | +| `registry+https://github.com/rust-lang/crates.io-index#regex@1.4.3` | `regex` | `1.4.3` | + +The following are some examples of specs for several different git dependencies: + +| Spec | Name | Version | +|:-----------------------------------------------------------|:----------------:|:--------:| +| `https://github.com/rust-lang/cargo#0.52.0` | `cargo` | `0.52.0` | +| `https://github.com/rust-lang/cargo#cargo-platform@0.1.2` | `cargo-platform` | `0.1.2` | +| `ssh://git@github.com/rust-lang/regex.git#regex@1.4.3` | `regex` | `1.4.3` | +| `git+ssh://git@github.com/rust-lang/regex.git#regex@1.4.3` | `regex` | `1.4.3` | +| `git+ssh://git@github.com/rust-lang/regex.git?branch=dev#regex@1.4.3` | `regex` | `1.4.3` | + +Local packages on the filesystem can use `file://` URLs to reference them: + +| Spec | Name | Version | +|:--------------------------------------------|:-----:|:-------:| +| `file:///path/to/my/project/foo` | `foo` | `*` | +| `file:///path/to/my/project/foo#1.1.8` | `foo` | `1.1.8` | +| `path+file:///path/to/my/project/foo#1.1.8` | `foo` | `1.1.8` | + +### 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 +one or more packages. Most commands generate an error if more than one package +could be referred to with the same specification. diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/profiles.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/profiles.md new file mode 100644 index 000000000..448543a5c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/profiles.md @@ -0,0 +1,488 @@ +# Profiles + +Profiles provide a way to alter the compiler settings, influencing things like +optimizations and debugging symbols. + +Cargo has 4 built-in profiles: `dev`, `release`, `test`, and `bench`. The +profile is automatically chosen based on which command is being run if a +profile is not specified on the command-line. In addition to the built-in +profiles, custom user-defined profiles can also be specified. + +Profile settings can be changed in [`Cargo.toml`](manifest.md) with the +`[profile]` table. Within each named profile, individual settings can be changed +with key/value pairs like this: + +```toml +[profile.dev] +opt-level = 1 # Use slightly better optimizations. +overflow-checks = false # Disable integer overflow checks. +``` + +Cargo only looks at the profile settings in the `Cargo.toml` manifest at the +root of the workspace. Profile settings defined in dependencies will be +ignored. + +Additionally, profiles can be overridden from a [config] definition. +Specifying a profile in a config file or environment variable will override +the settings from `Cargo.toml`. + +[config]: config.md + +## Profile settings + +The following is a list of settings that can be controlled in a profile. + +### 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 +the expense of longer compiler times. Higher levels may also change and +rearrange the compiled code which may make it harder to use with a debugger. + +The valid options are: + +* `0`: no optimizations +* `1`: basic optimizations +* `2`: some optimizations +* `3`: all optimizations +* `"s"`: optimize for binary size +* `"z"`: optimize for binary size, but also turn off loop vectorization. + +It is recommended to experiment with different levels to find the right +balance for your project. There may be surprising results, such as level `3` +being slower than `2`, or the `"s"` and `"z"` levels not being necessarily +smaller. You may also want to reevaluate your settings over time as newer +versions of `rustc` change optimization behavior. + +See also [Profile Guided Optimization] for more advanced optimization +techniques. + +[`-C opt-level` flag]: ../../rustc/codegen-options/index.html#opt-level +[Profile Guided Optimization]: ../../rustc/profile-guided-optimization.html + +### debug + +The `debug` setting controls the [`-C debuginfo` flag] which controls the +amount of debug information included in the compiled binary. + +The valid options are: + +* `0`, `false`, or `"none"`: no debug info at all, default for [`release`](#release) +* `"line-directives-only"`: line info directives only. For the nvptx* targets this enables [profiling]. For other use cases, `line-tables-only` is the better, more compatible choice. +* `"line-tables-only"`: line tables only. Generates the minimal amount of debug info for backtraces with filename/line number info, but not anything else, i.e. no variable or function parameter info. +* `1` or `"limited"`: debug info without type or variable-level information. Generates more detailed module-level info than `line-tables-only`. +* `2`, `true`, or `"full"`: full debug info, default for [`dev`](#dev) + +For more information on what each option does see `rustc`'s docs on [debuginfo]. + +You may wish to also configure the [`split-debuginfo`](#split-debuginfo) option +depending on your needs as well. + +> **MSRV:** 1.71 is required for `none`, `limited`, `full`, `line-directives-only`, and `line-tables-only` + +[`-C debuginfo` flag]: ../../rustc/codegen-options/index.html#debuginfo +[debuginfo]: ../../rustc/codegen-options/index.html#debuginfo +[profiling]: https://reviews.llvm.org/D46061 + +### split-debuginfo + +The `split-debuginfo` setting controls the [`-C split-debuginfo` flag] which +controls whether debug information, if generated, is either placed in the +executable itself or adjacent to it. + +This option is a string and acceptable values are the same as those the +[compiler accepts][`-C split-debuginfo` flag]. The default value for this option +is `unpacked` on macOS for profiles that have debug information otherwise +enabled. Otherwise the default for this option is [documented with rustc][`-C +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 + +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: + +```toml +[package] +# ... + +[profile.release] +strip = "debuginfo" +``` + +Possible string values of `strip` are `"none"`, `"debuginfo"`, and `"symbols"`. +The default is `"none"`. + +You can also configure this option with the boolean values `true` or `false`. +`strip = true` is equivalent to `strip = "symbols"`. `strip = false` is +equivalent to `strip = "none"` and disables `strip` completely. + +[`-C strip` flag]: ../../rustc/codegen-options/index.html#strip + +### debug-assertions + +The `debug-assertions` setting controls the [`-C debug-assertions` flag] which +turns `cfg(debug_assertions)` [conditional compilation] on or off. Debug +assertions are intended to include runtime validation which is only available +in debug/development builds. These may be things that are too expensive or +otherwise undesirable in a release build. Debug assertions enables the +[`debug_assert!` macro] in the standard library. + +The valid options are: + +* `true`: enabled +* `false`: disabled + +[`-C debug-assertions` flag]: ../../rustc/codegen-options/index.html#debug-assertions +[conditional compilation]: ../../reference/conditional-compilation.md#debug_assertions +[`debug_assert!` macro]: ../../std/macro.debug_assert.html + +### overflow-checks + +The `overflow-checks` setting controls the [`-C overflow-checks` flag] which +controls the behavior of [runtime integer overflow]. When overflow-checks are +enabled, a panic will occur on overflow. + +The valid options are: + +* `true`: enabled +* `false`: disabled + +[`-C overflow-checks` flag]: ../../rustc/codegen-options/index.html#overflow-checks +[runtime integer overflow]: ../../reference/expressions/operator-expr.md#overflow + +### 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]. +LTO can produce better optimized code, using whole-program analysis, at the cost +of longer linking time. + +The valid options are: + +* `false`: Performs "thin local LTO" which performs "thin" LTO on the local + crate only across its [codegen units](#codegen-units). No LTO is performed + if codegen units is 1 or [opt-level](#opt-level) is 0. +* `true` or `"fat"`: Performs "fat" LTO which attempts to perform + optimizations across all crates within the dependency graph. +* `"thin"`: Performs ["thin" LTO]. This is similar to "fat", but takes + substantially less time to run while still achieving performance gains + similar to "fat". +* `"off"`: Disables LTO. + +See the [linker-plugin-lto chapter] if you are interested in cross-language LTO. +This is not yet supported natively in Cargo, but can be performed via +`RUSTFLAGS`. + +[`-C lto`]: ../../rustc/codegen-options/index.html#lto +[link time optimizations]: https://llvm.org/docs/LinkTimeOptimization.html +[`-C linker-plugin-lto`]: ../../rustc/codegen-options/index.html#linker-plugin-lto +[`-C embed-bitcode`]: ../../rustc/codegen-options/index.html#embed-bitcode +[linker-plugin-lto chapter]: ../../rustc/linker-plugin-lto.html +["thin" LTO]: http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html + +### panic + +The `panic` setting controls the [`-C panic` flag] which controls which panic +strategy to use. + +The valid options are: + +* `"unwind"`: Unwind the stack upon panic. +* `"abort"`: Terminate the process upon panic. + +When set to `"unwind"`, the actual value depends on the default of the target +platform. For example, the NVPTX platform does not support unwinding, so it +always uses `"abort"`. + +Tests, benchmarks, build scripts, and proc macros ignore the `panic` setting. +The `rustc` test harness currently requires `unwind` behavior. See the +[`panic-abort-tests`] unstable flag which enables `abort` behavior. + +Additionally, when using the `abort` strategy and building a test, all of the +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 + +The `incremental` setting controls the [`-C incremental` flag] which controls +whether or not incremental compilation is enabled. Incremental compilation +causes `rustc` to save additional information to disk which will be reused +when recompiling the crate, improving re-compile times. The additional +information is stored in the `target` directory. + +The valid options are: + +* `true`: enabled +* `false`: disabled + +Incremental compilation is only used for workspace members and "path" +dependencies. + +The incremental value can be overridden globally with the `CARGO_INCREMENTAL` +[environment variable] or the [`build.incremental`] config variable. + +[`-C incremental` flag]: ../../rustc/codegen-options/index.html#incremental +[environment variable]: environment-variables.md +[`build.incremental`]: config.md#buildincremental + +### 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 +code generation units allows more of a crate to be processed in parallel +possibly reducing compile time, but may produce slower code. + +This option takes an integer greater than 0. + +The default is 256 for [incremental](#incremental) builds, and 16 for +non-incremental builds. + +[`-C codegen-units` flag]: ../../rustc/codegen-options/index.html#codegen-units + +### rpath + +The `rpath` setting controls the [`-C rpath` flag] which controls +whether or not [`rpath`] is enabled. + +[`-C rpath` flag]: ../../rustc/codegen-options/index.html#rpath +[`rpath`]: https://en.wikipedia.org/wiki/Rpath + +## Default profiles + +### 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`. + +The default settings for the `dev` profile are: + +```toml +[profile.dev] +opt-level = 0 +debug = true +split-debuginfo = '...' # Platform-specific. +strip = "none" +debug-assertions = true +overflow-checks = true +lto = false +panic = 'unwind' +incremental = true +codegen-units = 256 +rpath = false +``` + +### 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 +is the default for [`cargo install`]. + +The default settings for the `release` profile are: + +```toml +[profile.release] +opt-level = 3 +debug = false +split-debuginfo = '...' # Platform-specific. +strip = "none" +debug-assertions = false +overflow-checks = false +lto = false +panic = 'unwind' +incremental = false +codegen-units = 16 +rpath = false +``` + +### test + +The `test` profile is the default profile used by [`cargo test`]. +The `test` profile inherits the settings from the [`dev`](#dev) profile. + +### 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 + +To compile quickly, all profiles, by default, do not optimize build +dependencies (build scripts, proc macros, and their dependencies), and avoid +computing debug info when a build dependency is not used as a runtime +dependency. The default settings for build overrides are: + +```toml +[profile.dev.build-override] +opt-level = 0 +codegen-units = 256 +debug = false # when possible + +[profile.release.build-override] +opt-level = 0 +codegen-units = 256 +``` + +However, if errors occur while running build dependencies, turning full debug +info on will improve backtraces and debuggability when needed: + +```toml +debug = true +``` + +Build dependencies otherwise inherit settings from the active profile in use, as +described in [Profile selection](#profile-selection). + +## 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 +modes. When defining a custom profile, you must specify the `inherits` key to +specify which profile the custom profile inherits settings from when the +setting is not specified. + +For example, let's say you want to compare a normal release build with a +release build with [LTO](#lto) optimizations, you can specify something like +the following in `Cargo.toml`: + +```toml +[profile.release-lto] +inherits = "release" +lto = true +``` + +The `--profile` flag can then be used to choose this custom profile: + +```console +cargo build --profile release-lto +``` + +The output for each profile will be placed in a directory of the same name +as the profile in the [`target` directory]. As in the example above, the +output would go into the `target/release-lto` directory. + +[`target` directory]: build-cache.md + +## Profile selection + +The profile used depends on the command, the command-line flags like +`--release` or `--profile`, and the package (in the case of +[overrides](#overrides)). The default profile if none is specified is: + +| Command | Default Profile | +|---------|-----------------| +| [`cargo run`], [`cargo build`],
[`cargo check`], [`cargo rustc`] | [`dev` profile](#dev) | +| [`cargo test`] | [`test` profile](#test) +| [`cargo bench`] | [`bench` profile](#bench) +| [`cargo install`] | [`release` profile](#release) + +You can switch to a different profile using the `--profile=NAME` option which will used the given profile. +The `--release` flag is equivalent to `--profile=release`. + +The selected profile applies to all Cargo targets, +including [library](./cargo-targets.md#library), +[binary](./cargo-targets.md#binaries), +[example](./cargo-targets.md#examples), +[test](./cargo-targets.md#tests), +and [benchmark](./cargo-targets.md#benchmarks). + +The profile for specific packages can be specified with +[overrides](#overrides), described below. + +[`cargo bench`]: ../commands/cargo-bench.md +[`cargo build`]: ../commands/cargo-build.md +[`cargo check`]: ../commands/cargo-check.md +[`cargo install`]: ../commands/cargo-install.md +[`cargo run`]: ../commands/cargo-run.md +[`cargo rustc`]: ../commands/cargo-rustc.md +[`cargo test`]: ../commands/cargo-test.md + +## Overrides + +Profile settings can be overridden for specific packages and build-time +crates. To override the settings for a specific package, use the `package` +table to change the settings for the named package: + +```toml +# The `foo` package will use the -Copt-level=3 flag. +[profile.dev.package.foo] +opt-level = 3 +``` + +The package name is actually a [Package ID Spec](pkgid-spec.md), so you can +target individual versions of a package with syntax such as +`[profile.dev.package."foo:2.1.0"]`. + +To override the settings for all dependencies (but not any workspace member), +use the `"*"` package name: + +```toml +# Set the default for dependencies. +[profile.dev.package."*"] +opt-level = 2 +``` + +To override the settings for build scripts, proc macros, and their +dependencies, use the `build-override` table: + +```toml +# Set the settings for build scripts and proc-macros. +[profile.dev.build-override] +opt-level = 3 +``` + +> Note: When a dependency is both a normal dependency and a build dependency, +> Cargo will try to only build it once when `--target` is not specified. When +> using `build-override`, the dependency may need to be built twice, once as a +> normal dependency and once with the overridden build settings. This may +> increase initial build times. + +The precedence for which value is used is done in the following order (first +match wins): + +1. `[profile.dev.package.name]` --- A named package. +2. `[profile.dev.package."*"]` --- For any non-workspace member. +3. `[profile.dev.build-override]` --- Only for build scripts, proc macros, and + their dependencies. +4. `[profile.dev]` --- Settings in `Cargo.toml`. +5. Default values built-in to Cargo. + +Overrides cannot specify the `panic`, `lto`, or `rpath` settings. + +### Overrides and generics + +The location where generic code is instantiated will influence the +optimization settings used for that generic code. This can cause subtle +interactions when using profile overrides to change the optimization level of +a specific crate. If you attempt to raise the optimization level of a +dependency which defines generic functions, those generic functions may not be +optimized when used in your local crate. This is because the code may be +generated in the crate where it is instantiated, and thus may use the +optimization settings of that crate. + +For example, [nalgebra] is a library which defines vectors and matrices making +heavy use of generic parameters. If your local code defines concrete nalgebra +types like `Vector4` and uses their methods, the corresponding nalgebra +code will be instantiated and built within your crate. Thus, if you attempt to +increase the optimization level of `nalgebra` using a profile override, it may +not result in faster performance. + +Further complicating the issue, `rustc` has some optimizations where it will +attempt to share monomorphized generics between crates. If the opt-level is 2 +or 3, then a crate will not use monomorphized generics from other crates, nor +will it export locally defined monomorphized items to be shared with other +crates. When experimenting with optimizing dependencies for development, +consider trying opt-level 1, which will apply some optimizations while still +allowing monomorphized items to be shared. + +[nalgebra]: https://crates.io/crates/nalgebra diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/publishing.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/publishing.md new file mode 100644 index 000000000..f5ee95d0c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/publishing.md @@ -0,0 +1,296 @@ +# 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 +version is uploaded to be hosted on [crates.io]. + +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 + +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 +account (required for now). You will also need to provide and verify your email +address on the [Account Settings](https://crates.io/settings/profile) page. Once +that is done [create an API token](https://crates.io/settings/tokens), make sure +you copy it. Once you leave the page you will not be able to see it again. + +Then run the [`cargo login`] command. + +```console +$ cargo login +``` + +Then at the prompt put in the token specified. +```console +please paste the API Token found on https://crates.io/me below +abcdefghijklmnopqrstuvwxyz012345 +``` + +This command will inform Cargo of your API token and store it locally in your +`~/.cargo/credentials.toml`. Note that this token is a **secret** and should not be +shared with anyone else. If it leaks for any reason, you should revoke it +immediately. + +> **Note**: The [`cargo logout`] command can be used to remove the token from +> `credentials.toml`. This can be useful if you no longer need it stored on +> the local machine. + +## 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. + +Check out the [metadata you can specify](manifest.md) in `Cargo.toml` to +ensure your crate can be discovered more easily! Before publishing, make sure +you have filled out the following fields: + +- [`license` or `license-file`] +- [`description`] +- [`homepage`] +- [`repository`] +- [`readme`] + +It would also be a good idea to include some [`keywords`] and [`categories`], +though they are not required. + +If you are publishing a library, you may also want to consult the [Rust API +Guidelines]. + +### 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 +steps: + +1. Perform some verification checks on your package. +2. Compress your source code into a `.crate` file. +3. Extract the `.crate` file into a temporary directory and verify that it + compiles. +4. Upload the `.crate` file to [crates.io]. +5. The registry will perform some additional checks on the uploaded package + before adding it. + +It is recommended that you first run `cargo publish --dry-run` (or [`cargo +package`] which is equivalent) to ensure there aren't any warnings or errors +before publishing. This will perform the first three steps listed above. + +```console +$ cargo publish --dry-run +``` + +You can inspect the generated `.crate` file in the `target/package` directory. +[crates.io] currently has a 10MB size limit on the `.crate` file. You may want +to check the size of the `.crate` file to ensure you didn't accidentally +package up large assets that are not required to build your package, such as +test data, website documentation, or code generation. You can check which +files are included with the following command: + +```console +$ cargo package --list +``` + +Cargo will automatically ignore files ignored by your version control system +when packaging, but if you want to specify an extra set of files to ignore you +can use the [`exclude` key](manifest.md#the-exclude-and-include-fields) in the +manifest: + +```toml +[package] +# ... +exclude = [ + "public/assets/*", + "videos/*", +] +``` + +If you’d rather explicitly list the files to include, Cargo also supports an +`include` key, which if set, overrides the `exclude` key: + +```toml +[package] +# ... +include = [ + "**/*.rs", + "Cargo.toml", +] +``` + +## Uploading the crate + +When you are ready to publish, use the [`cargo publish`] command +to upload to [crates.io]: + +```console +$ cargo publish +``` + +And that’s it, you’ve now published your first 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. + +> **Recommendation:** Consider the full release process and automate what you can. +> +> Each version should include: +> - A changelog entry, preferably [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` + +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, +etc.). For situations such as this, Cargo supports a “yank” of a version of a +crate. + +```console +$ cargo yank --version 1.0.1 +$ cargo yank --version 1.0.1 --undo +``` + +A yank **does not** delete any code. This feature is not intended for deleting +accidentally uploaded secrets, for example. If that happens, you must reset +those secrets immediately. + +The semantics of a yanked version are that no new dependencies can be created +against that version, but all existing dependencies continue to work. One of the +major goals of [crates.io] is to act as a permanent archive of crates that does +not change over time, and allowing deletion of a version would go against this +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` + +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 +new versions of the crate, but an owner may designate additional owners. + +```console +$ cargo owner --add github-handle +$ cargo owner --remove github-handle +$ cargo owner --add github:rust-lang:owners +$ cargo owner --remove github:rust-lang:owners +``` + +The owner IDs given to these commands must be GitHub user names or GitHub teams. + +If a user name is given to `--add`, that user is invited as a “named” owner, with +full rights to the crate. In addition to being able to publish or yank versions +of the crate, they have the ability to add or remove owners, *including* the +owner that made *them* an owner. Needless to say, you shouldn’t make people you +don’t fully trust into a named owner. In order to become a named owner, a user +must have logged into [crates.io] previously. + +If a team name is given to `--add`, that team is invited as a “team” owner, with +restricted right to the crate. While they have permission to publish or yank +versions of the crate, they *do not* have the ability to add or remove owners. +In addition to being more convenient for managing groups of owners, teams are +just a bit more secure against owners becoming malicious. + +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 + +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: + +> It looks like you don’t have permission to query a necessary property from +GitHub to complete this request. You may need to re-authenticate on [crates.io] +to grant permission to read GitHub org memberships. + +This is basically a catch-all for “you tried to query a team, and one of the +five levels of membership access control denied this”. That is not an +exaggeration. GitHub’s support for team access control is Enterprise Grade. + +The most likely cause of this is simply that you last logged in before this +feature was added. We originally requested *no* permissions from GitHub when +authenticating users, because we didn’t actually ever use the user’s token for +anything other than logging them in. However to query team membership on your +behalf, we now require [the `read:org` scope][oauth-scopes]. + +You are free to deny us this scope, and everything that worked before teams +were introduced will keep working. However you will never be able to add a team +as an owner, or publish a crate as a team owner. If you ever attempt to do this, +you will get the error above. You may also see this error if you ever try to +publish a crate that you don’t own at all, but otherwise happens to have a team. + +If you ever change your mind, or just aren’t sure if [crates.io] has sufficient +permission, you can always go to and re-authenticate, +which will prompt you for permission if [crates.io] doesn’t have all the scopes +it would like to. + +An additional barrier to querying GitHub is that the organization may be +actively denying third party access. To check this, you can go to: + +```text +https://github.com/organizations/:org/settings/oauth_application_policy +``` + +where `:org` is the name of the organization (e.g., `rust-lang`). You may see +something like: + +![Organization Access Control](../images/org-level-acl.png) + +Where you may choose to explicitly remove [crates.io] from your organization’s +blacklist, or simply press the “Remove Restrictions” button to allow all third +party applications to access this data. + +Alternatively, when [crates.io] requested the `read:org` scope, you could have +explicitly whitelisted [crates.io] querying the org in question by pressing +the “Grant Access” button next to its name: + +![Authentication Access Control](../images/auth-level-acl.png) + +### Troubleshooting GitHub team access errors + +When trying to add a GitHub team as crate owner, you may see an error like: + +```text +error: failed to invite owners to crate : api errors (status 200 OK): could not find the github team org/repo +``` +In that case, you should go to [the GitHub Application settings page] and +check if crates.io is listed in the `Authorized OAuth Apps` tab. +If it isn't, you should go to and authorize it. +Then go back to the Application Settings page on GitHub, click on the +crates.io application in the list, and make sure you or your organization is +listed in the "Organization access" list with a green check mark. If there's +a button labeled `Grant` or `Request`, you should grant the access or +request the org owner to do so. + +[Rust API Guidelines]: https://rust-lang.github.io/api-guidelines/ +[`cargo login`]: ../commands/cargo-login.md +[`cargo logout`]: ../commands/cargo-logout.md +[`cargo package`]: ../commands/cargo-package.md +[`cargo publish`]: ../commands/cargo-publish.md +[`categories`]: manifest.md#the-categories-field +[`description`]: manifest.md#the-description-field +[`documentation`]: manifest.md#the-documentation-field +[`homepage`]: manifest.md#the-homepage-field +[`keywords`]: manifest.md#the-keywords-field +[`license` or `license-file`]: manifest.md#the-license-and-license-file-fields +[`readme`]: manifest.md#the-readme-field +[`repository`]: manifest.md#the-repository-field +[crates.io]: https://crates.io/ +[oauth-scopes]: https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/ +[the GitHub Application settings page]: https://github.com/settings/applications diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registries.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registries.md new file mode 100644 index 000000000..12c91f1ae --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registries.md @@ -0,0 +1,157 @@ +# Registries + +Cargo installs crates and fetches dependencies from a "registry". The default +registry is [crates.io]. A registry contains an "index" which contains a +searchable list of available crates. A registry may also provide a web API to +support publishing new crates directly from Cargo. + +> Note: If you are interested in mirroring or vendoring an existing registry, +> take a look at [Source Replacement]. + +If you are implementing a registry server, see [Running a Registry] for more +details about the protocol between Cargo and a 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` +table has a key for each registry, for example: + +```toml +[registries] +my-registry = { index = "https://my-intranet:8080/git/index" } +``` + +The `index` key should be a URL to a git repository with the registry's index or a +Cargo sparse registry URL with the `sparse+` prefix. + +A crate can then depend on a crate from another registry by specifying the +`registry` key and a value of the registry's name in that dependency's entry +in `Cargo.toml`: + +```toml +# Sample Cargo.toml +[package] +name = "my-project" +version = "0.1.0" +edition = "2024" + +[dependencies] +other-crate = { version = "1.0", registry = "my-registry" } +``` + +As with most config values, the index may be specified with an environment +variable instead of a config file. For example, setting the following +environment variable will accomplish the same thing as defining a config file: + +```ignore +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 + +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 +[`cargo publish`] take a `--registry` command-line flag to indicate which +registry to use. For example, to publish the package in the current directory: + +1. `cargo login --registry=my-registry` + + This only needs to be done once. You must enter the secret API token + retrieved from the registry's website. Alternatively the token may be + passed directly to the `publish` command with the `--token` command-line + flag or an environment variable with the name of the registry such as + `CARGO_REGISTRIES_MY_REGISTRY_TOKEN`. + +2. `cargo publish --registry=my-registry` + +Instead of always passing the `--registry` command-line option, the default +registry may be set in [`.cargo/config.toml`][config] with the `registry.default` +key. For example: + +```toml +[registry] +default = "my-registry" +``` + +Setting the `package.publish` key in the `Cargo.toml` manifest restricts which +registries the package is allowed to be published to. This is useful to +prevent accidentally publishing a closed-source package to [crates.io]. The +value may be a list of registry names, for example: + +```toml +[package] +# ... +publish = ["my-registry"] +``` + +The `publish` value may also be `false` to restrict all publishing, which is +the same as an empty list. + +The authentication information saved by [`cargo login`] is stored in the +`credentials.toml` file in the Cargo home directory (default `$HOME/.cargo`). It +has a separate table for each registry, for example: + +```toml +[registries.my-registry] +token = "854DvwSlUwEHtIo3kWy6x7UCPKHfzCmy" +``` + +## 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. + +The `git` protocol stores index metadata in a git repository and requires Cargo to clone +the entire repo. + +The `sparse` protocol fetches individual metadata files using plain HTTP requests. +Since Cargo only downloads the metadata for relevant crates, the `sparse` protocol can +save significant time and bandwidth. + +The [crates.io] registry supports both protocols. The protocol for crates.io is +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 +[config]: config.md +[crates.io]: https://crates.io/ +[`registries.crates-io.protocol`]: config.md#registriescrates-ioprotocol + + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-authentication.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-authentication.md new file mode 100644 index 000000000..6a6c5ce28 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-authentication.md @@ -0,0 +1,99 @@ +# 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: +```toml +# ~/.cargo/config.toml +[registry] +global-credential-providers = ["cargo:token", "cargo:libsecret", "cargo:macos-keychain", "cargo:wincred"] +``` +*Note that later entries have higher precedence. +See [`registry.global-credential-providers`](config.md#registryglobal-credential-providers) +for more details.* + +Some private registries may also recommend a registry-specific credential-provider. Check your +registry's documentation to see if this is the case. + +## 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__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:` 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. + +Any password manager with libsecret support can be used to view stored tokens. +The following are a few examples (non-exhaustive): + +- [GNOME Keyring](https://wiki.gnome.org/Projects/GnomeKeyring) +- [KDE Wallet Manager](https://apps.kde.org/kwalletmanager5/) (since KDE Frameworks 5.97.0) +- [KeePassXC](https://keepassxc.org/) (since 2.5.0) + +### `cargo:token-from-stdout ` +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 --account my.1password.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/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-index.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-index.md new file mode 100644 index 000000000..39abd4b6b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-index.md @@ -0,0 +1,327 @@ +# 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 +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 +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: + +```javascript +{ + "dl": "https://crates.io/api/v1/crates", + "api": "https://crates.io" +} +``` + +The keys are: +- `dl`: This is the URL for downloading crates listed in the index. The value + may have the following markers which will be replaced with their + corresponding value: + + - `{crate}`: The name of crate. + - `{version}`: The crate version. + - `{prefix}`: A directory prefix computed from the crate name. For example, + a crate named `cargo` has a prefix of `ca/rg`. See below for details. + - `{lowerprefix}`: Lowercase variant of `{prefix}`. + - `{sha256-checksum}`: The crate's sha256 checksum. + + If none of the markers are present, then the value + `/{crate}/{version}/download` is appended to the end. +- `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 +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 +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 +directories: + +- Packages with 1 character names are placed in a directory named `1`. +- Packages with 2 character names are placed in a directory named `2`. +- Packages with 3 character names are placed in the directory + `3/{first-character}` where `{first-character}` is the first character of + the package name. +- All other packages are stored in directories named + `{first-two}/{second-two}` where the top directory is the first two + characters of the package name, and the next subdirectory is the third and + fourth characters of the package name. For example, `cargo` would be stored + in a file named `ca/rg/cargo`. + +> Note: Although the index filenames are in lowercase, the fields that contain +> package names in `Cargo.toml` and the index JSON data are case-sensitive and +> may contain upper and lower case characters. + +The directory name above is calculated based on the package name converted to +lowercase; it is represented by the marker `{lowerprefix}`. When the original +package name is used without case conversion, the resulting directory name is +represented by the marker `{prefix}`. For example, the package `MyCrate` would +have a `{prefix}` of `My/Cr` and a `{lowerprefix}` of `my/cr`. In general, +using `{prefix}` is recommended over `{lowerprefix}`, but there are pros and +cons to each choice. Using `{prefix}` on case-insensitive filesystems results +in (harmless-but-inelegant) directory aliasing. For example, `crate` and +`CrateTwo` have `{prefix}` values of `cr/at` and `Cr/at`; these are distinct on +Unix machines but alias to the same directory on Windows. Using directories +with normalized case avoids aliasing, but on case-sensitive filesystems it's +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 + +Registries should consider enforcing limitations on package names added to +their index. Cargo itself allows names with any [alphanumeric], `-`, or `_` +characters. [crates.io] imposes its own limitations, including the following: + +- Only allows ASCII characters. +- Only alphanumeric, `-`, and `_` characters. +- First character must be alphabetic. +- Case-insensitive collision detection. +- Prevent differences of `-` vs `_`. +- Under a specific length (max 64). +- Rejects reserved names, such as Windows special filenames like "nul". + +Registries should consider incorporating similar restrictions, and consider +the security implications, such as [IDN homograph +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 + +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 + +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 +explaining the format of the entry. + +```javascript +{ + // The name of the package. + // This must only contain alphanumeric, `-`, or `_` characters. + "name": "foo", + // The version of the package this row is describing. + // This must be a valid version number according to the Semantic + // Versioning 2.0.0 spec at https://semver.org/. + "vers": "0.1.0", + // Array of direct dependencies of the package. + "deps": [ + { + // Name of the dependency. + // If the dependency is renamed from the original package name, + // this is the new name. The original package name is stored in + // the `package` field. + "name": "rand", + // The SemVer requirement for this dependency. + // This must be a valid version requirement defined at + // https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html. + "req": "^0.6", + // Array of features (as strings) enabled for this dependency. + // May be omitted since Cargo 1.84. + "features": ["i128_support"], + // Boolean of whether or not this is an optional dependency. + // Since Cargo 1.84, defaults to `false` if not specified. + "optional": false, + // Boolean of whether or not default features are enabled. + // Since Cargo 1.84, defaults to `true` if not specified. + "default_features": true, + // The target platform for the dependency. + // If not specified or `null`, it is not a target dependency. + // Otherwise, a string such as "cfg(windows)". + "target": null, + // The dependency kind. + // "dev", "build", or "normal". + // If not specified or `null`, it defaults to "normal". + "kind": "normal", + // The URL of the index of the registry where this dependency is + // from as a string. If not specified or `null`, it is assumed the + // dependency is in the current registry. + "registry": null, + // If the dependency is renamed, this is a string of the actual + // package name. If not specified or `null`, this dependency is not + // renamed. + "package": null, + } + ], + // A SHA256 checksum of the `.crate` file. + "cksum": "d867001db0e2b6e0496f9fac96930e2d42233ecd3ca0413e0753d4c7695d289c", + // Set of features defined for the package. + // Each feature maps to an array of features or dependencies it enables. + // May be omitted since Cargo 1.84. + "features": { + "extras": ["rand/simd_support"] + }, + // Boolean of whether or not this version has been yanked. + "yanked": false, + // The `links` string value from the package's manifest, or null if not + // specified. This field is optional and defaults to null. + "links": null, + // An unsigned 32-bit integer value indicating the schema version of this + // entry. + // + // If this is not specified, it should be interpreted as the default of 1. + // + // Cargo (starting with version 1.51) will ignore versions it does not + // recognize. 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. Versions older than 1.51 ignore this field, and + // thus may misinterpret the meaning of the index entry. + // + // The current values are: + // + // * 1: The schema as documented here, not including newer additions. + // This is honored in Rust version 1.51 and newer. + // * 2: The addition of the `features2` field. + // This is honored in Rust version 1.60 and newer. + "v": 2, + // This optional field contains features with new, extended syntax. + // Specifically, namespaced features (`dep:`) and weak dependencies + // (`pkg?/feat`). + // + // This is separated from `features` because versions older than 1.19 + // will fail to load due to not being able to parse the new syntax, even + // with a `Cargo.lock` file. + // + // Cargo will merge any values listed here with the "features" field. + // + // If this field is included, the "v" field should be set to at least 2. + // + // Registries are not required to use this field for extended feature + // syntax, they are allowed to include those in the "features" field. + // Using this is only necessary if the registry wants to support cargo + // versions older than 1.19, which in practice is only crates.io since + // those older versions do not support other registries. + "features2": { + "serde": ["dep:serde", "chrono?/serde"] + } + // The minimal supported Rust version (optional) + // This must be a valid version requirement without an operator (e.g. no `=`) + "rust_version": "1.60" +} +``` + +The JSON objects should not be modified after they are added except for the +`yanked` field whose value may change at any time. + +> **Note**: The index JSON format has subtle differences from the JSON format of the [Publish API] and [`cargo metadata`]. +> If you are using one of those as a source to generate index entries, you are encouraged to carefully inspect the documentation differences between them. +> +> For the [Publish API], the differences are: +> +> * `deps` +> * `name` --- When the dependency is [renamed] in `Cargo.toml`, the publish API puts the original package name in the `name` field and the aliased name in the `explicit_name_in_toml` field. +> The index places the aliased name in the `name` field, and the original package name in the `package` field. +> * `req` --- The Publish API field is called `version_req`. +> * `cksum` --- The publish API does not specify the checksum, it must be computed by the registry before adding to the index. +> * `features` --- Some features may be placed in the `features2` field. +> Note: This is only a legacy requirement for [crates.io]; other registries should not need to bother with modifying the features map. +> The `v` field indicates the presence of the `features2` field. +> * The publish API includes several other fields, such as `description` and `readme`, which don't appear in the index. +> These are intended to make it easier for a registry to obtain the metadata about the crate to display on a website without needing to extract and parse the `.crate` file. +> This additional information is typically added to a database on the registry server. +> * Although `rust_version` is included here, [crates.io] will ignore this field +> and instead read it from the `Cargo.toml` contained in the `.crate` file. +> +> For [`cargo metadata`], the differences are: +> +> * `vers` --- The `cargo metadata` field is called `version`. +> * `deps` +> * `name` --- When the dependency is [renamed] in `Cargo.toml`, `cargo metadata` puts the original package name in the `name` field and the aliased name in the `rename` field. +> The index places the aliased name in the `name` field, and the original package name in the `package` field. +> * `default_features` --- The `cargo metadata` field is called `uses_default_features`. +> * `registry` --- `cargo metadata` uses a value of `null` to indicate that the dependency comes from [crates.io]. +> The index uses a value of `null` to indicate that the dependency comes from the same registry as the index. +> When creating an index entry, a registry other than [crates.io] should translate a value of `null` to be `https://github.com/rust-lang/crates.io-index` and translate a URL that matches the current index to be `null`. +> * `cargo metadata` includes some extra fields, such as `source` and `path`. +> * The index includes additional fields such as `yanked`, `cksum`, and `v`. + +[renamed]: specifying-dependencies.md#renaming-dependencies-in-cargotoml +[Publish API]: registry-web-api.md#publish +[`cargo metadata`]: ../commands/cargo-metadata.md + +## 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 +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 +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/`. + +The sparse protocol downloads each index file using an individual HTTP request. Since +this results in a large number of small HTTP requests, performance is significantly +improved with a server that supports pipelining and HTTP/2. + +#### 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=""` 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 +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 +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 +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 +the equivalent git URL when the sparse protocol is used. + +If a registry does offer both protocols, it's currently recommended to choose one protocol +as the canonical protocol and use [source replacement] for the other protocol. + + +[`cargo publish`]: ../commands/cargo-publish.md +[alphanumeric]: ../../std/primitive.char.html#method.is_alphanumeric +[crates.io]: https://crates.io/ +[source replacement]: ../reference/source-replacement.md +[#10964]: https://github.com/rust-lang/cargo/issues/10964 diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-web-api.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-web-api.md new file mode 100644 index 000000000..e8481b3a4 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/registry-web-api.md @@ -0,0 +1,362 @@ +# Web API + +A registry may host a web API at the location defined in `config.json` to +support any of the actions listed below. + +Cargo includes the `Authorization` header for requests that require +authentication. The header value is the API token. The server should respond +with a 403 response code if the token is not valid. Users are expected to +visit the registry's website to obtain a token, and Cargo can store the token +using the [`cargo login`] command, or by passing the token on the +command-line. + +Responses use a 2xx response code for success. +Errors should use an appropriate response code, such as 404. +Failure +responses should have a JSON object with the following structure: + +```javascript +{ + // Array of errors to display to the user. + "errors": [ + { + // The error message as a string. + "detail": "error message text" + } + ] +} +``` + +If the response has this structure Cargo will display the detailed message to the user, even if the response code is 200. +If the response code indicates an error and the content does not have this structure, Cargo will display to the user a + message intended to help debugging the server error. A server returning an `errors` object allows a registry to provide a more +detailed or user-centric error message. + +For backwards compatibility, servers should ignore any unexpected query +parameters or JSON fields. If a JSON field is missing, it should be assumed to +be null. The endpoints are versioned with the `v1` component of the path, and +Cargo is responsible for handling backwards compatibility fallbacks should any +be required in the future. + +Cargo sets the following headers for all requests: + +- `Content-Type`: `application/json` (for requests with a body payload) +- `Accept`: `application/json` +- `User-Agent`: The Cargo version such as `cargo/1.32.0 (8610973aa + 2019-01-02)`. This may be modified by the user in a configuration value. + Added in 1.29. + +## Publish + +- Endpoint: `/api/v1/crates/new` +- Method: PUT +- Authorization: Included + +The publish endpoint is used to publish a new version of a crate. The server +should validate the crate, make it available for download, and add it to the +index. + +It is not required for the index to be updated before the successful response is sent. +After a successful response, Cargo will poll the index for a short period of time to identify that the new crate has been added. +If the crate does not appear in the index after a short period of time, then Cargo will display a warning letting the user know that the new crate is not yet available. + +The body of the data sent by Cargo is: + +- 32-bit unsigned little-endian integer of the length of JSON data. +- Metadata of the package as a JSON object. +- 32-bit unsigned little-endian integer of the length of the `.crate` file. +- The `.crate` file. + +The following is a commented example of the JSON object. Some notes of some +restrictions imposed by [crates.io] are included only to illustrate some +suggestions on types of validation that may be done, and should not be +considered as an exhaustive list of restrictions [crates.io] imposes. + +```javascript +{ + // The name of the package. + "name": "foo", + // The version of the package being published. + "vers": "0.1.0", + // Array of direct dependencies of the package. + "deps": [ + { + // Name of the dependency. + // If the dependency is renamed from the original package name, + // this is the original name. The new package name is stored in + // the `explicit_name_in_toml` field. + "name": "rand", + // The semver requirement for this dependency. + "version_req": "^0.6", + // Array of features (as strings) enabled for this dependency. + "features": ["i128_support"], + // Boolean of whether or not this is an optional dependency. + "optional": false, + // Boolean of whether or not default features are enabled. + "default_features": true, + // The target platform for the dependency. + // null if not a target dependency. + // Otherwise, a string such as "cfg(windows)". + "target": null, + // The dependency kind. + // "dev", "build", or "normal". + "kind": "normal", + // The URL of the index of the registry where this dependency is + // from as a string. If not specified or null, it is assumed the + // dependency is in the current registry. + "registry": null, + // If the dependency is renamed, this is a string of the new + // package name. If not specified or null, this dependency is not + // renamed. + "explicit_name_in_toml": null, + } + ], + // Set of features defined for the package. + // Each feature maps to an array of features or dependencies it enables. + // Cargo does not impose limitations on feature names, but crates.io + // requires alphanumeric ASCII, `_` or `-` characters. + "features": { + "extras": ["rand/simd_support"] + }, + // List of strings of the authors. + // May be empty. + "authors": ["Alice "], + // Description field from the manifest. + // May be null. crates.io requires at least some content. + "description": null, + // String of the URL to the website for this package's documentation. + // May be null. + "documentation": null, + // String of the URL to the website for this package's home page. + // May be null. + "homepage": null, + // String of the content of the README file. + // May be null. + "readme": null, + // String of a relative path to a README file in the crate. + // May be null. + "readme_file": null, + // Array of strings of keywords for the package. + "keywords": [], + // Array of strings of categories for the package. + "categories": [], + // String of the license for the package. + // May be null. crates.io requires either `license` or `license_file` to be set. + "license": null, + // String of a relative path to a license file in the crate. + // May be null. + "license_file": null, + // String of the URL to the website for the source repository of this package. + // May be null. + "repository": null, + // Optional object of "status" badges. Each value is an object of + // arbitrary string to string mappings. + // crates.io has special interpretation of the format of the badges. + "badges": { + "travis-ci": { + "branch": "master", + "repository": "rust-lang/cargo" + } + }, + // The `links` string value from the package's manifest, or null if not + // specified. This field is optional and defaults to null. + "links": null, + // The minimal supported Rust version (optional) + // This must be a valid version requirement without an operator (e.g. no `=`) + "rust_version": null +} +``` + +A successful response includes the JSON object: + +```javascript +{ + // Optional object of warnings to display to the user. + "warnings": { + // Array of strings of categories that are invalid and ignored. + "invalid_categories": [], + // Array of strings of badge names that are invalid and ignored. + "invalid_badges": [], + // Array of strings of arbitrary warnings to display to the user. + "other": [] + } +} +``` + +## Yank + +- Endpoint: `/api/v1/crates/{crate_name}/{version}/yank` +- Method: DELETE +- Authorization: Included + +The yank endpoint will set the `yank` field of the given version of a crate to +`true` in the index. + +A successful response includes the JSON object: + +```javascript +{ + // Indicates the yank succeeded, always true. + "ok": true, +} +``` + +## Unyank + +- Endpoint: `/api/v1/crates/{crate_name}/{version}/unyank` +- Method: PUT +- Authorization: Included + +The unyank endpoint will set the `yank` field of the given version of a crate +to `false` in the index. + +A successful response includes the JSON object: + +```javascript +{ + // Indicates the unyank succeeded, always true. + "ok": true, +} +``` + +## 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 +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 + +- Endpoint: `/api/v1/crates/{crate_name}/owners` +- Method: GET +- Authorization: Included + +The owners endpoint returns a list of owners of the crate. + +A successful response includes the JSON object: + +```javascript +{ + // Array of owners of the crate. + "users": [ + { + // Unique unsigned 32-bit integer of the owner. + "id": 70, + // The unique username of the owner. + "login": "github:rust-lang:core", + // Name of the owner. + // This is optional and may be null. + "name": "Core", + } + ] +} +``` + +### Owners: Add + +- Endpoint: `/api/v1/crates/{crate_name}/owners` +- Method: PUT +- Authorization: Included + +A PUT request will send a request to the registry to add a new owner to a +crate. It is up to the registry how to handle the request. For example, +[crates.io] sends an invite to the user that they must accept before being +added. + +The request should include the following JSON object: + +```javascript +{ + // Array of `login` strings of owners to add. + "users": ["login_name"] +} +``` + +A successful response includes the JSON object: + +```javascript +{ + // Indicates the add succeeded, always true. + "ok": true, + // A string to be displayed to the user. + "msg": "user ehuss has been invited to be an owner of crate cargo" +} +``` + +### Owners: Remove + +- Endpoint: `/api/v1/crates/{crate_name}/owners` +- Method: DELETE +- Authorization: Included + +A DELETE request will remove an owner from a crate. The request should include +the following JSON object: + +```javascript +{ + // Array of `login` strings of owners to remove. + "users": ["login_name"] +} +``` + +A successful response includes the JSON object: + +```javascript +{ + // Indicates the remove succeeded, always true. + "ok": true + // A string to be displayed to the user. Currently ignored by cargo. + "msg": "owners successfully removed", +} +``` + +## Search + +- Endpoint: `/api/v1/crates` +- Method: GET +- Query Parameters: + - `q`: The search query string. + - `per_page`: Number of results, default 10, max 100. + +The search request will perform a search for crates, using criteria defined on +the server. + +A successful response includes the JSON object: + +```javascript +{ + // Array of results. + "crates": [ + { + // Name of the crate. + "name": "rand", + // The highest version available. + "max_version": "0.6.1", + // Textual description of the crate. + "description": "Random number generators and other randomness functionality.\n", + } + ], + "meta": { + // Total number of results available on the server. + "total": 119 + } +} +``` + +## Login + +- Endpoint: `/me` + +The "login" endpoint is not an actual API request. It exists solely for the +[`cargo login`] command to display a URL to instruct a user to visit in a web +browser to log in and retrieve an API token. + +[`cargo login`]: ../commands/cargo-login.md +[`cargo package`]: ../commands/cargo-package.md +[`cargo publish`]: ../commands/cargo-publish.md +[alphanumeric]: ../../std/primitive.char.html#method.is_alphanumeric +[config]: config.md +[crates.io]: https://crates.io/ +[publishing documentation]: publishing.md#cargo-owner diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/resolver.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/resolver.md new file mode 100644 index 000000000..a21c2926d --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/resolver.md @@ -0,0 +1,715 @@ +# Dependency Resolution + +One of Cargo's primary tasks is to determine the versions of dependencies to +use based on the version requirements specified in each package. This process +is called "dependency resolution" and is performed by the "resolver". The +result of the resolution is stored in the `Cargo.lock` file which "locks" the +dependencies to specific versions, and keeps them fixed over time. +The [`cargo tree`] command can be used to visualize the result of the +resolver. + +[dependency specifications]: specifying-dependencies.md +[dependency specification]: specifying-dependencies.md +[`cargo tree`]: ../commands/cargo-tree.md + +## Constraints and Heuristics + +In many cases there is no single "best" dependency resolution. +The resolver operates under various constraints and heuristics to find a generally applicable resolution. +To understand how these interact, it is helpful to have a coarse understanding of how dependency resolution works. + +This pseudo-code approximates what Cargo's resolver does: +```rust +pub fn resolve(workspace: &[Package], policy: Policy) -> Option { + let dep_queue = Queue::new(workspace); + let resolved = ResolveGraph::new(); + resolve_next(pkq_queue, resolved, policy) +} + +fn resolve_next(dep_queue: Queue, resolved: ResolveGraph, policy: Policy) -> Option { + let Some(dep_spec) = policy.pick_next_dep(dep_queue) else { + // Done + return Some(resolved); + }; + + if let Some(resolved) = policy.try_unify_version(dep_spec, resolved.clone()) { + return Some(resolved); + } + + let dep_versions = dep_spec.lookup_versions()?; + let mut dep_versions = policy.filter_versions(dep_spec, dep_versions); + while let Some(dep_version) = policy.pick_next_version(&mut dep_versions) { + if policy.needs_version_unification(dep_version, &resolved) { + continue; + } + + let mut dep_queue = dep_queue.clone(); + dep_queue.enqueue(dep_version.dependencies); + let mut resolved = resolved.clone(); + resolved.register(dep_version); + if let Some(resolved) = resolve_next(dep_queue, resolved) { + return Some(resolved); + } + } + + // No valid solution found, backtrack and `pick_next_version` + None +} +``` + +Key steps: +- Walking dependencies (`pick_next_dep`): + The order dependencies are walked can affect + how related version requirements for the same dependency get resolved, see unifying versions, + and how much the resolver backtracks, affecting resolver performance, +- Unifying versions (`try_unify_version`, `needs_version_unification`): + Cargo reuses versions where possible to reduce build times and allow types from common dependencies to be passed between APIs. + If multiple versions would have been unified if it wasn't for conflicts in their [dependency specifications], Cargo will backtrack, erroring if no solution is found, rather than selecting multiple versions. + A [dependency specification] or Cargo may decide that a version is undesirable, + preferring to backtrack or error rather than use it. +- Preferring versions (`pick_next_version`): + Cargo may decide that it should prefer a specific version, + falling back to the next version when backtracking. + +### Version numbers + +Generally, Cargo prefers the highest version currently available. + +For example, if you had a package in the resolve graph with: +```toml +[dependencies] +bitflags = "*" +``` +If at the time the `Cargo.lock` file is generated, the greatest version of +`bitflags` is `1.2.1`, then the package will use `1.2.1`. + +For an example of a possible exception, see [Rust version](#rust-version). + +### Version requirements + +Package specify what versions they support, rejecting all others, through +[version requirements]. + +For example, if you had a package in the resolve graph with: +```toml +[dependencies] +bitflags = "1.0" # meaning `>=1.0.0,<2.0.0` +``` +If at the time the `Cargo.lock` file is generated, the greatest version of +`bitflags` is `1.2.1`, then the package will use `1.2.1` because it is the +greatest within the compatibility range. If `2.0.0` is published, it will +still use `1.2.1` because `2.0.0` is considered incompatible. + +[version requirements]: specifying-dependencies.md#version-requirement-syntax + +### SemVer compatibility + +Cargo assumes packages follow [SemVer] and will unify dependency versions if they are +[SemVer] compatible according to the [Caret version requirements]. +If two compatible versions cannot be unified because of conflicting version requirements, +Cargo will error. + +See the [SemVer Compatibility] chapter for guidance on what is considered a +"compatible" change. + +Examples: + +The following two packages will have their dependencies on `bitflags` unified because any version picked will be compatible with each other. +```toml +# Package A +[dependencies] +bitflags = "1.0" # meaning `>=1.0.0,<2.0.0` + +# Package B +[dependencies] +bitflags = "1.1" # meaning `>=1.1.0,<2.0.0` +``` + +The following packages will error because the version requirements conflict, selecting two distinct compatible versions. +```toml +# Package A +[dependencies] +log = "=0.4.11" + +# Package B +[dependencies] +log = "=0.4.8" +``` + +The following two packages will not have their dependencies on `rand` unified because only incompatible versions are available for each. +Instead, two different versions (e.g. 0.6.5 and 0.7.3) will be resolved and built. +This can lead to potential problems, see the [Version-incompatibility hazards] section for more details. +```toml +# Package A +[dependencies] +rand = "0.7" # meaning `>=0.7.0,<0.8.0` + +# Package B +[dependencies] +rand = "0.6" # meaning `>=0.6.0,<0.7.0` +``` + +Generally, the following two packages will not have their dependencies unified because incompatible versions are available that satisfy the version requirements: +Instead, two different versions (e.g. 0.6.5 and 0.7.3) will be resolved and built. +The application of other constraints or heuristics may cause these to be unified, +picking one version (e.g. 0.6.5). +```toml +# Package A +[dependencies] +rand = ">=0.6,<0.8.0" + +# Package B +[dependencies] +rand = "0.6" # meaning `>=0.6.0,<0.7.0` +``` + +[SemVer]: https://semver.org/ +[SemVer Compatibility]: semver.md +[Caret version requirements]: specifying-dependencies.md#default-requirements +[Version-incompatibility hazards]: #version-incompatibility-hazards + +#### Version-incompatibility hazards + +When multiple versions of a crate appear in the resolve graph, this can cause +problems when types from those crates are exposed by the crates using them. +This is because the types and items are considered different by the Rust +compiler, even if they have the same name. Libraries should take care when +publishing a SemVer-incompatible version (for example, publishing `2.0.0` +after `1.0.0` has been in use), particularly for libraries that are widely +used. + +The "[semver trick]" is a workaround for this problem of publishing a breaking +change while retaining compatibility with older versions. The linked page goes +into detail about what the problem is and how to address it. In short, when a +library wants to publish a SemVer-breaking release, publish the new release, +and also publish a point release of the previous version that reexports the +types from the newer version. + +These incompatibilities usually manifest as a compile-time error, but +sometimes they will only appear as a runtime misbehavior. For example, let's +say there is a common library named `foo` that ends up appearing with both +version `1.0.0` and `2.0.0` in the resolve graph. If [`downcast_ref`] is used +on a object created by a library using version `1.0.0`, and the code calling +`downcast_ref` is downcasting to a type from version `2.0.0`, the downcast +will fail at runtime. + +It is important to make sure that if you have multiple versions of a library +that you are properly using them, especially if it is ever possible for the +types from different versions to be used together. The [`cargo tree +-d`][`cargo tree`] command can be used to identify duplicate versions and +where they come from. Similarly, it is important to consider the impact on the +ecosystem if you publish a SemVer-incompatible version of a popular library. + +[semver trick]: https://github.com/dtolnay/semver-trick +[`downcast_ref`]: ../../std/any/trait.Any.html#method.downcast_ref + +### Rust version + +To support developing software with a minimum supported [Rust version], +the resolver can take into account a dependency version's compatibility with your Rust version. +This is controlled by the config field [`resolver.incompatible-rust-versions`]. + +With the `fallback` setting, the resolver will prefer packages with a Rust version that is +less than or equal to your own Rust version. +For example, you are using Rust 1.85 to develop the following package: +```toml +[package] +name = "my-cli" +rust-version = "1.62" + +[dependencies] +clap = "4.0" # resolves to 4.0.32 +``` +The resolver would pick version 4.0.32 because it has a Rust version of 1.60.0. +- 4.0.0 is not picked because it is a [lower version number](#version-numbers) despite it also having a Rust version of 1.60.0. +- 4.5.20 is not picked because it is incompatible with `my-cli`'s Rust version of 1.62 despite having a much [higher version](#version-numbers) and it has a Rust version of 1.74.0 which is compatible with your 1.85 toolchain. + +If a version requirement does not include a Rust version compatible dependency version, +the resolver won't error but will instead pick a version, even if its potentially suboptimal. +For example, you change the dependency on `clap`: +```toml +[package] +name = "my-cli" +rust-version = "1.62" + +[dependencies] +clap = "4.2" # resolves to 4.5.20 +``` +No version of `clap` matches that [version requirement](#version-requirements) +that is compatible with Rust version 1.62. +The resolver will then pick an incompatible version, like 4.5.20 despite it having a Rust version of 1.74. + +When the resolver selects a dependency version of a package, +it does not know all the workspace members that will eventually have a transitive dependency on that version +and so it cannot take into account only the Rust versions relevant for that dependency. +The resolver has heuristics to find a "good enough" solution when workspace members have different Rust versions. +This applies even for packages in a workspace without a Rust version. + +When a workspace has members with different Rust versions, +the resolver may pick a lower dependency version than necessary. +For example, you have the following workspace members: +```toml +[package] +name = "a" +rust-version = "1.62" + +[package] +name = "b" + +[dependencies] +clap = "4.2" # resolves to 4.5.20 +``` +Though package `b` does not have a Rust version and could use a higher version like 4.5.20, +4.0.32 will be selected because of package `a`'s Rust version of 1.62. + +Or the resolver may pick too high of a version. +For example, you have the following workspace members: +```toml +[package] +name = "a" +rust-version = "1.62" + +[dependencies] +clap = "4.2" # resolves to 4.5.20 + +[package] +name = "b" + +[dependencies] +clap = "4.5" # resolves to 4.5.20 +``` +Though each package has a version requirement for `clap` that would meet its own Rust version, +because of [version unification](#version-numbers), +the resolver will need to pick one version that works in both cases and that would be a version like 4.5.20. + +[Rust version]: rust-version.md +[`resolver.incompatible-rust-versions`]: config.md#resolverincompatible-rust-versions + +### Features + +For the purpose of generating `Cargo.lock`, the resolver builds the dependency +graph as-if all [features] of all [workspace] members are enabled. This +ensures that any optional dependencies are available and properly resolved +with the rest of the graph when features are added or removed with the +[`--features` command-line flag](features.md#command-line-feature-options). +The resolver runs a second time to determine the actual features used when +*compiling* a crate, based on the features selected on the command-line. + +Dependencies are resolved with the union of all features enabled on them. For +example, if one package depends on the [`im`] package with the [`serde` +dependency] enabled and another package depends on it with the [`rayon` +dependency] enabled, then `im` will be built with both features enabled, and +the `serde` and `rayon` crates will be included in the resolve graph. If no +packages depend on `im` with those features, then those optional dependencies +will be ignored, and they will not affect resolution. + +When building multiple packages in a workspace (such as with `--workspace` or +multiple `-p` flags), the features of the dependencies of all of those +packages are unified. If you have a circumstance where you want to avoid that +unification for different workspace members, you will need to build them via +separate `cargo` invocations. + +The resolver will skip over versions of packages that are missing required +features. For example, if a package depends on version `^1` of [`regex`] with +the [`perf` feature], then the oldest version it can select is `1.3.0`, +because versions prior to that did not contain the `perf` feature. Similarly, +if a feature is removed from a new release, then packages that require that +feature will be stuck on the older releases that contain that feature. It is +discouraged to remove features in a SemVer-compatible release. Beware that +optional dependencies also define an implicit feature, so removing an optional +dependency or making it non-optional can cause problems, see [removing an +optional dependency]. + +[`im`]: https://crates.io/crates/im +[`perf` feature]: https://github.com/rust-lang/regex/blob/1.3.0/Cargo.toml#L56 +[`rayon` dependency]: https://github.com/bodil/im-rs/blob/v15.0.0/Cargo.toml#L47 +[`regex`]: https://crates.io/crates/regex +[`serde` dependency]: https://github.com/bodil/im-rs/blob/v15.0.0/Cargo.toml#L46 +[features]: features.md +[removing an optional dependency]: semver.md#cargo-remove-opt-dep +[workspace]: workspaces.md + +#### Feature resolver version 2 + +When `resolver = "2"` is specified in `Cargo.toml` (see [resolver +versions](#resolver-versions) below), a different feature resolver is used +which uses a different algorithm for unifying features. The version `"1"` +resolver will unify features for a package no matter where it is specified. +The version `"2"` resolver will avoid unifying features in the following +situations: + +* Features for target-specific dependencies are not enabled if the target is + not currently being built. For example: + + ```toml + [dependencies.common] + version = "1.0" + features = ["f1"] + + [target.'cfg(windows)'.dependencies.common] + version = "1.0" + features = ["f2"] + ``` + + When building this example for a non-Windows platform, the `f2` feature will + *not* be enabled. + +* Features enabled on [build-dependencies] or proc-macros will not be unified + when those same dependencies are used as a normal dependency. For example: + + ```toml + [dependencies] + log = "0.4" + + [build-dependencies] + log = {version = "0.4", features=['std']} + ``` + + When building the build script, the `log` crate will be built with the `std` + feature. When building the library of your package, it will not enable the + feature. + +* Features enabled on [dev-dependencies] will not be unified when those same + dependencies are used as a normal dependency, unless those dev-dependencies + are currently being built. For example: + + ```toml + [dependencies] + serde = {version = "1.0", default-features = false} + + [dev-dependencies] + serde = {version = "1.0", features = ["std"]} + ``` + + In this example, the library will normally link against `serde` without the + `std` feature. However, when built as a test or example, it will include the + `std` feature. For example, `cargo test` or `cargo build --all-targets` will + unify these features. Note that dev-dependencies in dependencies are always + ignored, this is only relevant for the top-level package or workspace + members. + +[build-dependencies]: specifying-dependencies.md#build-dependencies +[dev-dependencies]: specifying-dependencies.md#development-dependencies +[resolver-field]: features.md#resolver-versions + +### `links` + +The [`links` field] is used to ensure only one copy of a native library is +linked into a binary. The resolver will attempt to find a graph where there is +only one instance of each `links` name. If it is unable to find a graph that +satisfies that constraint, it will return an error. + +For example, it is an error if one package depends on [`libgit2-sys`] version +`0.11` and another depends on `0.12`, because Cargo is unable to unify those, +but they both link to the `git2` native library. Due to this requirement, it +is encouraged to be very careful when making SemVer-incompatible releases with +the `links` field if your library is in common use. + +[`links` field]: manifest.md#the-links-field +[`libgit2-sys`]: https://crates.io/crates/libgit2-sys + +### Yanked versions + +[Yanked releases][yank] are those that are marked that they should not be +used. When the resolver is building the graph, it will ignore all yanked +releases unless they already exist in the `Cargo.lock` file or are explicitly +requested by the [`--precise`] flag of `cargo update` (nightly only). + +[yank]: publishing.md#cargo-yank +[`--precise`]: ../commands/cargo-update.md#option-cargo-update---precise + +## Dependency updates + +Dependency resolution is automatically performed by all Cargo commands that +need to know about the dependency graph. For example, [`cargo build`] will run +the resolver to discover all the dependencies to build. After the first time +it runs, the result is stored in the `Cargo.lock` file. Subsequent commands +will run the resolver, keeping dependencies locked to the versions in +`Cargo.lock` *if it can*. + +If the dependency list in `Cargo.toml` has been modified, for example changing +the version of a dependency from `1.0` to `2.0`, then the resolver will select +a new version for that dependency that matches the new requirements. If that +new dependency introduces new requirements, those new requirements may also +trigger additional updates. The `Cargo.lock` file will be updated with the new +result. The `--locked` or `--frozen` flags can be used to change this behavior +to prevent automatic updates when requirements change, and return an error +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 `--recursive` or `--precise` can +be used to control how versions are selected. + +[`cargo build`]: ../commands/cargo-build.md +[`cargo update`]: ../commands/cargo-update.md + +## Overrides + +Cargo has several mechanisms to override dependencies within the graph. The +[Overriding Dependencies] chapter goes into detail on how to use overrides. +The overrides appear as an overlay to a registry, replacing the patched +version with the new entry. Otherwise, resolution is performed like normal. + +[Overriding Dependencies]: overriding-dependencies.md + +## Dependency kinds + +There are three kinds of dependencies in a package: normal, [build], and +[dev][dev-dependencies]. For the most part these are all treated the same from +the perspective of the resolver. One difference is that dev-dependencies for +non-workspace members are always ignored, and do not influence resolution. + +[Platform-specific dependencies] with the `[target]` table are resolved as-if +all platforms are enabled. In other words, the resolver ignores the platform +or `cfg` expression. + +[build]: specifying-dependencies.md#build-dependencies +[dev-dependencies]: specifying-dependencies.md#development-dependencies +[Platform-specific dependencies]: specifying-dependencies.md#platform-specific-dependencies + +### dev-dependency cycles + +Usually the resolver does not allow cycles in the graph, but it does allow +them for [dev-dependencies]. For example, project "foo" has a dev-dependency +on "bar", which has a normal dependency on "foo" (usually as a "path" +dependency). This is allowed because there isn't really a cycle from the +perspective of the build artifacts. In this example, the "foo" library is +built (which does not need "bar" because "bar" is only used for tests), and +then "bar" can be built depending on "foo", then the "foo" tests can be built +linking to "bar". + +Beware that this can lead to confusing errors. In the case of building library +unit tests, there are actually two copies of the library linked into the final +test binary: the one that was linked with "bar", and the one built that +contains the unit tests. Similar to the issues highlighted in the +[Version-incompatibility hazards] section, the types between the two are not +compatible. Be careful when exposing types of "foo" from "bar" in this +situation, since the "foo" unit tests won't treat them the same as the local +types. + +If possible, try to split your package into multiple packages and restructure +it so that it remains strictly acyclic. + +## Resolver versions + +Different resolver behavior can be specified through the resolver +version in `Cargo.toml` like this: + +```toml +[package] +name = "my-package" +version = "1.0.0" +resolver = "2" +``` +- `"1"` (default) +- `"2"` ([`edition = "2021"`](manifest.md#the-edition-field) default): Introduces changes in [feature +unification](#features). See the [features chapter][features-2] for more +details. +- `"3"` ([`edition = "2024"`](manifest.md#the-edition-field) default, requires Rust 1.84+): Change the default for [`resolver.incompatible-rust-versions`] from `allow` to `fallback` + +The resolver is a global option that affects the entire workspace. The +`resolver` version in dependencies is ignored, only the value in the top-level +package will be used. If using a [virtual workspace], the version should be +specified in the `[workspace]` table, for example: + +```toml +[workspace] +members = ["member1", "member2"] +resolver = "2" +``` + +> **MSRV:** Requires 1.51+ + +[virtual workspace]: workspaces.md#virtual-workspace +[features-2]: features.md#feature-resolver-version-2 + +## Recommendations + +The following are some recommendations for setting the version within your +package, and for specifying dependency requirements. These are general +guidelines that should apply to common situations, but of course some +situations may require specifying unusual requirements. + +* Follow the [SemVer guidelines] when deciding how to update your version + number, and whether or not you will need to make a SemVer-incompatible + version change. +* Use caret requirements for dependencies, such as `"1.2.3"`, for most + situations. This ensures that the resolver can be maximally flexible in + choosing a version while maintaining build compatibility. + * Specify all three components with the version you are currently using. + This helps set the minimum version that will be used, and ensures that + other users won't end up with an older version of the dependency that + might be missing something that your package requires. + * Avoid `*` requirements, as they are not allowed on [crates.io], and they + can pull in SemVer-breaking changes during a normal `cargo update`. + * Avoid overly broad version requirements. For example, `>=2.0.0` can pull + in any SemVer-incompatible version, like version `5.0.0`, which can result + in broken builds in the future. + * Avoid overly narrow version requirements if possible. For example, if you + specify a tilde requirement like `bar="~1.3"`, and another package + specifies a requirement of `bar="1.4"`, this will fail to resolve, even + though minor releases should be compatible. +* Try to keep the dependency versions up-to-date with the actual minimum + versions that your library requires. For example, if you have a requirement + of `bar="1.0.12"`, and then in a future release you start using new features + added in the `1.1.0` release of "bar", update your dependency requirement to + `bar="1.1.0"`. + + 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 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 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 + that won't work well if the two are out of sync (and it is never expected to + use the two libraries independently). The parent library can use an `=` + requirement on the proc-macro, and re-export the macros for easy access. +* `0.0.x` versions can be used for packages that are permanently unstable. + +In general, the stricter you make the dependency requirements, the more likely +it will be for the resolver to fail. Conversely, if you use requirements that +are too loose, it may be possible for new versions to be published that will +break the build. + +[SemVer guidelines]: semver.md +[crates.io]: https://crates.io/ + +## Troubleshooting + +The following illustrates some problems you may experience, and some possible +solutions. + +### Why was a dependency included? + +Say you see dependency `rand` in the `cargo check` output but don't think it's needed and want to understand why it's being pulled in. + +You can run +```console +$ cargo tree --workspace --target all --all-features --invert rand +rand v0.8.5 +└── ... + +rand v0.8.5 +└── ... +``` + +### Why was that feature on this dependency enabled? + +You might identify that it was an activated feature that caused `rand` to show up. **To figure out which package activated the feature, you can add the `--edges features`** +```console +$ cargo tree --workspace --target all --all-features --edges features --invert rand +rand v0.8.5 +└── ... + +rand v0.8.5 +└── ... +``` + +### Unexpected dependency duplication + +You see multiple instances of `rand` when you run +```console +$ cargo tree --workspace --target all --all-features --duplicates +rand v0.7.3 +└── ... + +rand v0.8.5 +└── ... +``` + +The resolver algorithm has converged on a solution that includes two copies of a +dependency when one would suffice. For example: + +```toml +# Package A +[dependencies] +rand = "0.7" + +# Package B +[dependencies] +rand = ">=0.6" # note: open requirements such as this are discouraged +``` + +In this example, Cargo may build two copies of the `rand` crate, even though a +single copy at version `0.7.3` would meet all requirements. This is because the +resolver's algorithm favors building the latest available version of `rand` for +Package B, which is `0.8.5` at the time of this writing, and that is +incompatible with Package A's specification. The resolver's algorithm does not +currently attempt to "deduplicate" in this situation. + +The use of open-ended version requirements like `>=0.6` is discouraged in Cargo. +But, if you run into this situation, the [`cargo update`] command with the +`--precise` flag can be used to manually remove such duplications. + +[`cargo update`]: ../commands/cargo-update.md + +### Why wasn't a newer version selected? + +Say you noticed that the latest version of a dependency wasn't selected when you ran: +```console +$ cargo update +``` +You can enable some extra logging to see why this happened: +```console +$ env CARGO_LOG=cargo::core::resolver=trace cargo update +``` +**Note:** Cargo log targets and levels may change over time. + +### SemVer-breaking patch release breaks the build + +Sometimes a project may inadvertently publish a point release with a +SemVer-breaking change. When users update with `cargo update`, they will pick +up this new release, and then their build may break. In this situation, it is +recommended that the project should [yank] the release, and either remove the +SemVer-breaking change, or publish it as a new SemVer-major version increase. + +If the change happened in a third-party project, if possible try to +(politely!) work with the project to resolve the issue. + +While waiting for the release to be yanked, some workarounds depend on the +circumstances: + +* If your project is the end product (such as a binary executable), just avoid + updating the offending package in `Cargo.lock`. This can be done with the + `--precise` flag in [`cargo update`]. +* If you publish a binary on [crates.io], then you can temporarily add an `=` + requirement to force the dependency to a specific good version. + * Binary projects can alternatively recommend users to use the `--locked` + flag with [`cargo install`] to use the original `Cargo.lock` that contains + the known good version. +* Libraries may also consider publishing a temporary new release with stricter + requirements that avoid the troublesome dependency. You may want to consider + using range requirements (instead of `=`) to avoid overly-strict + requirements that may conflict with other packages using the same + dependency. Once the problem has been resolved, you can publish another + point release that relaxes the dependency back to a caret requirement. +* If it looks like the third-party project is unable or unwilling to yank the + release, then one option is to update your code to be compatible with the + changes, and update the dependency requirement to set the minimum version to + the new release. You will also need to consider if this is a SemVer-breaking + change of your own library, for example if it exposes types from the + dependency. + +[`cargo install`]: ../commands/cargo-install.md + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/running-a-registry.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/running-a-registry.md new file mode 100644 index 000000000..87ab08ede --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/running-a-registry.md @@ -0,0 +1,20 @@ +# 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 +[`cargo package`]. Users won't be able to use Cargo to publish to it, but this +may be sufficient for closed environments. The index format is described in +[Registry Index]. + +A full-featured registry that supports publishing will additionally need to +have a web API service that conforms to the API used by Cargo. The web API is +described in [Registry Web API]. + +Commercial and community projects are available for building and running a +registry. See +for a list of what is available. + +[Registry Web API]: registry-web-api.md +[Registry Index]: registry-index.md +[`cargo publish`]: ../commands/cargo-publish.md +[`cargo package`]: ../commands/cargo-package.md diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/rust-version.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/rust-version.md new file mode 100644 index 000000000..f961efd48 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/rust-version.md @@ -0,0 +1,164 @@ +# Rust Version + +The `rust-version` field is an optional key that tells cargo what version of the +Rust toolchain you support for your package. + +```toml +[package] +# ... +rust-version = "1.56" +``` + +The Rust version must be a bare version number with at least one component; it +cannot include semver operators or pre-release identifiers. Compiler pre-release +identifiers such as -nightly will be ignored while checking the Rust version. + +> **MSRV:** Respected as of 1.56 + +## Uses + +**Diagnostics:** + +When your package is compiled on an unsupported toolchain, +Cargo will provide clearer diagnostics about the insufficient toolchain version rather than reporting invalid syntax or missing functionality in the standard library. +This affects all [Cargo targets](cargo-targets.md) in the package, including binaries, examples, test suites, +benchmarks, etc. + +**Development aid:** + +`cargo add` will auto-select the dependency's version requirement to be the latest version compatible with your `rust-version`. +If that isn't the latest version, `cargo add` will inform users so they can make the choice on whether to keep it or update your `rust-version`. + +The [resolver](resolver.md#rust-version) may take Rust version into account when picking dependencies. + +Other tools may also take advantage of it, like `cargo clippy`'s +[`incompatible_msrv` lint](https://rust-lang.github.io/rust-clippy/stable/index.html#/incompatible_msrv). + +> **Note:** The `rust-version` may be ignored using the `--ignore-rust-version` option. + +## Support Expectations + +These are general expectations; some packages may document when they do not follow these. + +**Complete:** + +All functionality, including binaries and API, are available on the supported Rust versions under every [feature](features.md). + +**Verified:** + +A package's functionality is verified on its supported Rust versions, including automated testing. +See also our +[Rust version CI guide](../guide/continuous-integration.md#verifying-rust-version). + +**Patchable:** + +When licenses allow it, +users can [override their local dependency](overriding-dependencies.md) with a fork of your package. +In this situation, Cargo may load the entire workspace for the patched dependency which should work on the supported Rust versions, even if other packages in the workspace have different supported Rust versions. + +**Dependency Support:** + +In support of the above, +it is expected that each dependency's version-requirement supports at least one version compatible with your `rust-version`. +However, +it is **not** expected that the dependency specification excludes versions incompatible with your `rust-version`. +In fact, supporting both allows you to balance the needs of users that support older Rust versions with those that don't. + +## Setting and Updating Rust Version + +What Rust versions to support is a trade off between +- Costs for the maintainer in not using newer features of the Rust toolchain or their dependencies +- Costs to users who would benefit from a package using newer features of a toolchain, e.g. reducing build times by migrating to a feature in the standard library from a polyfill +- Availability of a package to users supporting older Rust versions + +> **Note:** [Changing `rust-version`](semver.md#env-new-rust) is assumed to be a minor incompatibility + +> **Recommendation:** Choose a policy for what Rust versions to support and when that is changed so users can compare it with their own policy and, +> if it isn't compatible, +> decide whether the loss of general improvements or the risk of a blocking bug that won't be fixed is acceptable or not. +> +> The simplest policy to support is to always use the latest Rust version. +> +> Depending on your risk profile, the next simplest approach is to continue to support old major or minor versions of your package that support older Rust versions. + +### Selecting supported Rust versions + +Users of your package are most likely to track their supported Rust versions to: +- Their Rust toolchain vendor's support policy, e.g. The Rust Project or a Linux distribution + - Note: the Rust Project only offers bug fixes and security updates for the latest version. +- A fixed schedule for users to re-verify their packages with the new toolchain, e.g. the first release of the year, every 5 releases. + +In addition, users are unlikely to be using the new Rust version immediately but need time to notice and re-verify or might not be aligned on the exact same schedule.. + +Example version policies: +- "N-2", meaning "latest version with a 2 release grace window for updating" +- Every even release with a 2 release grace window for updating +- Every version from this calendar year with a one year grace window for updating + +> **Note:** To find the minimum `rust-version` compatible with your project as-is, you can use third-party tools like [`cargo-msrv`](https://crates.io/crates/cargo-msrv). + +### Update timeline + +When your policy specifies you no longer need to support a Rust version, you can update `rust-version` immediately or when needed. + +By allowing `rust-version` to drift from your policy, +you offer users more of a grace window for upgrading. +However, this is too unpredictable to be relied on for aligning with the Rust version users track. + +The further `rust-version` drifts from your specified policy, +the more likely users are to infer a policy you did not intend, +leading to frustration at the unmet expectations. + +When drift is allowed, +there is the question of what is "justifiable enough" to drop supported Versions. +Each person can come to a reasonably different justification; +working through that discussion can be frustrating for the involved parties. +This will disempower those who would want to avoid that type of conflict, +which is particularly the case for new or casual contributors who either +feel that they are not in a position to raise the question or +that the conflict may hurt the chance of their change being merged. + +### Multiple Policies in a Workspace + +Cargo allows supporting multiple policies within one workspace. + +Verifying specific packages under specific Rust versions can get complicated. +Tools like [`cargo-hack`](https://crates.io/crates/cargo-hack) can help. + +For any dependency shared across policies, +the lowest common versions must be used as Cargo +[unifies SemVer-compatible versions](resolver.md#semver-compatibility), +potentially limiting access to features of the shared dependency for the workspace member with the higher `rust-version`. + +To allow users to patch a dependency on one of your workspace members, +every package in the workspace would need to be loadable in the oldest Rust version supported by the workspace. + +When using [`incompatible-rust-versions = "fallback"`](config.md#resolverincompatible-rust-versions), +the Rust version of one package can affect dependency versions selected for another package with a different Rust version. +See the [resolver](resolver.md#rust-version) chapter for more details. + +### One or More Policies + +One way to mitigate the downsides of supporting older Rust versions is to apply your policy to older major or minor versions of your package that you continue to support. +You likely still need a policy for what Rust versions the development branch support compared to the release branches for those major or minor versions. + +Only updating the development branch when "needed"' can help reduce the number of supported release branches. + +There is the question of what can be backported into these release branches. +By backporting new functionality between minor versions, +the next available version would be missing it which could be considered a breaking change, violating SemVer. +Backporting changes also comes with the risk of introducing bugs. + +Supporting older versions comes at a cost. +This cost is dependent on the risk and impact of bugs within the package and what is acceptable for backporting. +Creating the release branches on-demand and putting the backport burden on the community are ways to balance this cost. + +There is not yet a way for dependency management tools to report that a non-latest version is still supported, +shifting the responsibility to users to notice this in documentation. + +For example, a Rust version support policy could look like: +- The development branch tracks to the latest stable release from the Rust Project, updated when needed + - The minor version will be raised when changing `rust-version` +- The project supports every version for this calendar year, with another year grace window + - The last minor version that supports a supported Rust version will receive community provided bug fixes + - Fixes must be backported to all supported minor releases between the development branch and the needed supported Rust version diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/semver.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/semver.md new file mode 100644 index 000000000..d740c6b1b --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/semver.md @@ -0,0 +1,2319 @@ +# SemVer Compatibility + +This chapter provides details on what is conventionally considered a +compatible or breaking SemVer change for new releases of a package. See the +[SemVer compatibility] section for details on what SemVer is, and how Cargo +uses it to ensure compatibility of libraries. + +These are only *guidelines*, and not necessarily hard-and-fast rules that all +projects will obey. The [Change categories] section details how this guide +classifies the level and severity of a change. Most of this guide focuses on +changes that will cause `cargo` and `rustc` to fail to build something that +previously worked. Almost every change carries some risk that it will +negatively affect the runtime behavior, and for those cases it is usually a +judgment call by the project maintainers whether or not it is a +SemVer-incompatible change. + +[Change categories]: #change-categories +[SemVer compatibility]: resolver.md#semver-compatibility + +## Change categories + +All of the policies listed below are categorized by the level of change: + +* **Major change**: a change that requires a major SemVer bump. +* **Minor change**: a change that requires only a minor SemVer bump. +* **Possibly-breaking change**: a change that some projects may consider major + and others consider minor. + +The "Possibly-breaking" category covers changes that have the *potential* to +break during an update, but may not necessarily cause a breakage. The impact +of these changes should be considered carefully. The exact nature will depend +on the change and the principles of the project maintainers. + +Some projects may choose to only bump the patch number on a minor change. It +is encouraged to follow the SemVer spec, and only apply bug fixes in patch +releases. However, a bug fix may require an API change that is marked as a +"minor change", and shouldn't affect compatibility. This guide does not take a +stance on how each individual "minor change" should be treated, as the +difference between minor and patch changes are conventions that depend on the +nature of the change. + +Some changes are marked as "minor", even though they carry the potential risk +of breaking a build. This is for situations where the potential is extremely +low, and the potentially breaking code is unlikely to be written in idiomatic +Rust, or is specifically discouraged from use. + +This guide uses the terms "major" and "minor" assuming this relates to a +"1.0.0" release or later. Initial development releases starting with "0.y.z" +can treat changes in "y" as a major release, and "z" as a minor release. +"0.0.z" releases are always major changes. This is because Cargo uses the +convention that only changes in the left-most non-zero component are +considered incompatible. + +* API compatibility + * Items + * [Major: renaming/moving/removing any public items](#item-remove) + * [Minor: adding new public items](#item-new) + * Types + * [Major: Changing the alignment, layout, or size of a well-defined type](#type-layout) + * Structs + * [Major: adding a private struct field when all current fields are public](#struct-add-private-field-when-public) + * [Major: adding a public field when no private field exists](#struct-add-public-field-when-no-private) + * [Minor: adding or removing private fields when at least one already exists](#struct-private-fields-with-private) + * [Minor: going from a tuple struct with all private fields (with at least one field) to a normal struct, or vice versa](#struct-tuple-normal-with-private) + * Enums + * [Major: adding new enum variants (without `non_exhaustive`)](#enum-variant-new) + * [Major: adding new fields to an enum variant](#enum-fields-new) + * Traits + * [Major: adding a non-defaulted trait item](#trait-new-item-no-default) + * [Major: any change to trait item signatures](#trait-item-signature) + * [Possibly-breaking: adding a defaulted trait item](#trait-new-default-item) + * [Major: adding a trait item that makes the trait non-object safe](#trait-object-safety) + * [Major: adding a type parameter without a default](#trait-new-parameter-no-default) + * [Minor: adding a defaulted trait type parameter](#trait-new-parameter-default) + * Implementations + * [Possibly-breaking change: adding any inherent items](#impl-item-new) + * Generics + * [Major: tightening generic bounds](#generic-bounds-tighten) + * [Minor: loosening generic bounds](#generic-bounds-loosen) + * [Minor: adding defaulted type parameters](#generic-new-default) + * [Minor: generalizing a type to use generics (with identical types)](#generic-generalize-identical) + * [Major: generalizing a type to use generics (with possibly different types)](#generic-generalize-different) + * [Minor: changing a generic type to a more generic type](#generic-more-generic) + * [Major: capturing more generic parameters in RPIT](#generic-rpit-capture) + * Functions + * [Major: adding/removing function parameters](#fn-change-arity) + * [Possibly-breaking: introducing a new function type parameter](#fn-generic-new) + * [Minor: generalizing a function to use generics (supporting original type)](#fn-generalize-compatible) + * [Major: generalizing a function to use generics with type mismatch](#fn-generalize-mismatch) + * [Minor: making an `unsafe` function safe](#fn-unsafe-safe) + * Attributes + * [Major: switching from `no_std` support to requiring `std`](#attr-no-std-to-std) + * [Major: adding `non_exhaustive` to an existing enum, variant, or struct with no private fields](#attr-adding-non-exhaustive) +* Tooling and environment compatibility + * [Possibly-breaking: changing the minimum version of Rust required](#env-new-rust) + * [Possibly-breaking: changing the platform and environment requirements](#env-change-requirements) + * [Minor: introducing new lints](#new-lints) + * Cargo + * [Minor: adding a new Cargo feature](#cargo-feature-add) + * [Major: removing a Cargo feature](#cargo-feature-remove) + * [Major: removing a feature from a feature list if that changes functionality or public items](#cargo-feature-remove-another) + * [Possibly-breaking: removing an optional dependency](#cargo-remove-opt-dep) + * [Minor: changing dependency features](#cargo-change-dep-feature) + * [Minor: adding dependencies](#cargo-dep-add) +* [Application compatibility](#application-compatibility) + +## API compatibility + +All of the examples below contain three parts: the original code, the code +after it has been modified, and an example usage of the code that could appear +in another project. In a minor change, the example usage should successfully +build with both the before and after versions. + +### Major: renaming/moving/removing any public items {#item-remove} + +The absence of a publicly exposed [item][items] will cause any uses of that item to +fail to compile. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// After +// ... item has been removed + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + updated_crate::foo(); // Error: cannot find function `foo` +} +``` + +This includes adding any sort of [`cfg` attribute] which can change which +items or behavior is available based on [conditional compilation]. + +Mitigating strategies: +* Mark items to be removed as [deprecated], and then remove them at a later + date in a SemVer-breaking release. +* Mark renamed items as [deprecated], and use a [`pub use`] item to re-export + to the old name. + +### Minor: adding new public items {#item-new} + +Adding new, public [items] is a minor change. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +// ... absence of item + +/////////////////////////////////////////////////////////// +// After +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +// `foo` is not used since it didn't previously exist. +``` + +Note that in some rare cases this can be a **breaking change** due to glob +imports. For example, if you add a new trait, and a project has used a glob +import that brings that trait into scope, and the new trait introduces an +associated item that conflicts with any types it is implemented on, this can +cause a compile-time error due to the ambiguity. Example: + +```rust,ignore +// Breaking change example + +/////////////////////////////////////////////////////////// +// Before +// ... absence of trait + +/////////////////////////////////////////////////////////// +// After +pub trait NewTrait { + fn foo(&self) {} +} + +impl NewTrait for i32 {} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::*; + +pub trait LocalTrait { + fn foo(&self) {} +} + +impl LocalTrait for i32 {} + +fn main() { + 123i32.foo(); // Error: multiple applicable items in scope +} +``` + +This is not considered a major change because conventionally glob imports are +a known forwards-compatibility hazard. Glob imports of items from external +crates should be avoided. + +### Major: Changing the alignment, layout, or size of a well-defined type {#type-layout} + +It is a breaking change to change the alignment, layout, or size of a type that was previously well-defined. + +In general, types that use the [the default representation] do not have a well-defined alignment, layout, or size. +The compiler is free to alter the alignment, layout, or size, so code should not make any assumptions about it. + +> **Note**: It may be possible for external crates to break if they make assumptions about the alignment, layout, or size of a type even if it is not well-defined. +> This is not considered a SemVer breaking change since those assumptions should not be made. + +Some examples of changes that are not a breaking change are (assuming no other rules in this guide are violated): + +* Adding, removing, reordering, or changing fields of a default representation struct, union, or enum in such a way that the change follows the other rules in this guide (for example, using `non_exhaustive` to allow those changes, or changes to private fields that are already private). + See [struct-add-private-field-when-public](#struct-add-private-field-when-public), [struct-add-public-field-when-no-private](#struct-add-public-field-when-no-private), [struct-private-fields-with-private](#struct-private-fields-with-private), [enum-fields-new](#enum-fields-new). +* Adding variants to a default representation enum, if the enum uses `non_exhaustive`. + This may change the alignment or size of the enumeration, but those are not well-defined. + See [enum-variant-new](#enum-variant-new). +* Adding, removing, reordering, or changing private fields of a `repr(C)` struct, union, or enum, following the other rules in this guide (for example, using `non_exhaustive`, or adding private fields when other private fields already exist). + See [repr-c-private-change](#repr-c-private-change). +* Adding variants to a `repr(C)` enum, if the enum uses `non_exhaustive`. + See [repr-c-enum-variant-new](#repr-c-enum-variant-new). +* Adding `repr(C)` to a default representation struct, union, or enum. + See [repr-c-add](#repr-c-add). +* Adding `repr()` [primitive representation] to an enum. + See [repr-int-enum-add](#repr-int-enum-add). +* Adding `repr(transparent)` to a default representation struct or enum. + See [repr-transparent-add](#repr-transparent-add). + +Types that use the [`repr` attribute] can be said to have an alignment and layout that is defined in some way that code may make some assumptions about that may break as a result of changing that type. + +In some cases, types with a `repr` attribute may not have an alignment, layout, or size that is well-defined. +In these cases, it may be safe to make changes to the types, though care should be exercised. +For example, types with private fields that do not otherwise document their alignment, layout, or size guarantees cannot be relied upon by external crates since the public API does not fully define the alignment, layout, or size of the type. + +A common example where a type with *private* fields is well-defined is a type with a single private field with a generic type, using `repr(transparent)`, +and the prose of the documentation discusses that it is transparent to the generic type. +For example, see [`UnsafeCell`]. + +Some examples of breaking changes are: + +* Adding `repr(packed)` to a struct or union. + See [repr-packed-add](#repr-packed-add). +* Adding `repr(align)` to a struct, union, or enum. + See [repr-align-add](#repr-align-add). +* Removing `repr(packed)` from a struct or union. + See [repr-packed-remove](#repr-packed-remove). +* Changing the value N of `repr(packed(N))` if that changes the alignment or layout. + See [repr-packed-n-change](#repr-packed-n-change). +* Changing the value N of `repr(align(N))` if that changes the alignment. + See [repr-align-n-change](#repr-align-n-change). +* Removing `repr(align)` from a struct, union, or enum. + See [repr-align-remove](#repr-align-remove). +* Changing the order of public fields of a `repr(C)` type. + See [repr-c-shuffle](#repr-c-shuffle). +* Removing `repr(C)` from a struct, union, or enum. + See [repr-c-remove](#repr-c-remove). +* Removing `repr()` from an enum. + See [repr-int-enum-remove](#repr-int-enum-remove). +* Changing the primitive representation of a `repr()` enum. + See [repr-int-enum-change](#repr-int-enum-change). +* Removing `repr(transparent)` from a struct or enum. + See [repr-transparent-remove](#repr-transparent-remove). + +[the default representation]: ../../reference/type-layout.html#the-default-representation +[primitive representation]: ../../reference/type-layout.html#primitive-representations +[`repr` attribute]: ../../reference/type-layout.html#representations +[`std::mem::transmute`]: ../../std/mem/fn.transmute.html +[`UnsafeCell`]: ../../std/cell/struct.UnsafeCell.html#memory-layout + +#### Minor: `repr(C)` add, remove, or change a private field {#repr-c-private-change} + +It is usually safe to add, remove, or change a private field of a `repr(C)` struct, union, or enum, assuming it follows the other guidelines in this guide (see [struct-add-private-field-when-public](#struct-add-private-field-when-public), [struct-add-public-field-when-no-private](#struct-add-public-field-when-no-private), [struct-private-fields-with-private](#struct-private-fields-with-private), [enum-fields-new](#enum-fields-new)). + +For example, adding private fields can only be done if there are already other private fields, or it is `non_exhaustive`. +Public fields may be added if there are private fields, or it is `non_exhaustive`, and the addition does not alter the layout of the other fields. + +However, this may change the size and alignment of the type. +Care should be taken if the size or alignment changes. +Code should not make assumptions about the size or alignment of types with private fields or `non_exhaustive` unless it has a documented size or alignment. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[derive(Default)] +#[repr(C)] +pub struct Example { + pub f1: i32, + f2: i32, // a private field +} + +/////////////////////////////////////////////////////////// +// After +#[derive(Default)] +#[repr(C)] +pub struct Example { + pub f1: i32, + f2: i32, + f3: i32, // a new field +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +fn main() { + // NOTE: Users should not make assumptions about the size or alignment + // since they are not documented. + let f = updated_crate::Example::default(); +} +``` + +#### Minor: `repr(C)` add enum variant {#repr-c-enum-variant-new} + +It is usually safe to add variants to a `repr(C)` enum, if the enum uses `non_exhaustive`. +See [enum-variant-new](#enum-variant-new) for more discussion. + +Note that this may be a breaking change since it changes the size and alignment of the type. +See [repr-c-private-change](#repr-c-private-change) for similar concerns. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(C)] +#[non_exhaustive] +pub enum Example { + Variant1 { f1: i16 }, + Variant2 { f1: i32 }, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(C)] +#[non_exhaustive] +pub enum Example { + Variant1 { f1: i16 }, + Variant2 { f1: i32 }, + Variant3 { f1: i64 }, // added +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +fn main() { + // NOTE: Users should not make assumptions about the size or alignment + // since they are not specified. For example, this raised the size from 8 + // to 16 bytes. + let f = updated_crate::Example::Variant2 { f1: 123 }; +} +``` + +#### Minor: Adding `repr(C)` to a default representation {#repr-c-add} + +It is safe to add `repr(C)` to a struct, union, or enum with [the default representation]. +This is safe because users should not make assumptions about the alignment, layout, or size of types with the default representation. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Example { + pub f1: i32, + pub f2: i16, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(C)] // added +pub struct Example { + pub f1: i32, + pub f2: i16, +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +fn main() { + let f = updated_crate::Example { f1: 123, f2: 456 }; +} +``` + +#### Minor: Adding `repr()` to an enum {#repr-int-enum-add} + +It is safe to add `repr()` [primitive representation] to an enum with [the default representation]. +This is safe because users should not make assumptions about the alignment, layout, or size of an enum with the default representation. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub enum E { + Variant1, + Variant2(i32), + Variant3 { f1: f64 }, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(i32)] // added +pub enum E { + Variant1, + Variant2(i32), + Variant3 { f1: f64 }, +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +fn main() { + let x = updated_crate::E::Variant3 { f1: 1.23 }; +} +``` + +#### Minor: Adding `repr(transparent)` to a default representation struct or enum {#repr-transparent-add} + +It is safe to add `repr(transparent)` to a struct or enum with [the default representation]. +This is safe because users should not make assumptions about the alignment, layout, or size of a struct or enum with the default representation. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[derive(Default)] +pub struct Example(T); + +/////////////////////////////////////////////////////////// +// After +#[derive(Default)] +#[repr(transparent)] // added +pub struct Example(T); + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +fn main() { + let x = updated_crate::Example::::default(); +} +``` + +#### Major: Adding `repr(packed)` to a struct or union {#repr-packed-add} + +It is a breaking change to add `repr(packed)` to a struct or union. +Making a type `repr(packed)` makes changes that can break code, such as being invalid to take a reference to a field, or causing truncation of disjoint closure captures. + + + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Example { + pub f1: u8, + pub f2: u16, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(packed)] // added +pub struct Example { + pub f1: u8, + pub f2: u16, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + let f = updated_crate::Example { f1: 1, f2: 2 }; + let x = &f.f2; // Error: reference to packed field is unaligned +} +``` + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Example(pub i32, pub i32); + +/////////////////////////////////////////////////////////// +// After +#[repr(packed)] +pub struct Example(pub i32, pub i32); + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + let mut f = updated_crate::Example(123, 456); + let c = || { + // Without repr(packed), the closure precisely captures `&f.0`. + // With repr(packed), the closure captures `&f` to avoid undefined behavior. + let a = f.0; + }; + f.1 = 789; // Error: cannot assign to `f.1` because it is borrowed + c(); +} +``` + +#### Major: Adding `repr(align)` to a struct, union, or enum {#repr-align-add} + +It is a breaking change to add `repr(align)` to a struct, union, or enum. +Making a type `repr(align)` would break any use of that type in a `repr(packed)` type because that combination is not allowed. + + + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Aligned { + pub a: i32, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(align(8))] // added +pub struct Aligned { + pub a: i32, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Aligned; + +#[repr(packed)] +pub struct Packed { // Error: packed type cannot transitively contain a `#[repr(align)]` type + f1: Aligned, +} + +fn main() { + let p = Packed { + f1: Aligned { a: 123 }, + }; +} +``` + +#### Major: Removing `repr(packed)` from a struct or union {#repr-packed-remove} + +It is a breaking change to remove `repr(packed)` from a struct or union. +This may change the alignment or layout that extern crates are relying on. + +If any fields are public, then removing `repr(packed)` may change the way disjoint closure captures work. +In some cases, this can cause code to break, similar to those outlined in the [edition guide][edition-closures]. + +[edition-closures]: ../../edition-guide/rust-2021/disjoint-capture-in-closures.html + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(C, packed)] +pub struct Packed { + pub a: u8, + pub b: u16, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(C)] // removed packed +pub struct Packed { + pub a: u8, + pub b: u16, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Packed; + +fn main() { + let p = Packed { a: 1, b: 2 }; + // Some assumption about the size of the type. + // Without `packed`, this fails since the size is 4. + const _: () = assert!(std::mem::size_of::() == 3); // Error: evaluation of constant value failed +} +``` + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(C, packed)] +pub struct Packed { + pub a: *mut i32, + pub b: i32, +} +unsafe impl Send for Packed {} + +/////////////////////////////////////////////////////////// +// After +#[repr(C)] // removed packed +pub struct Packed { + pub a: *mut i32, + pub b: i32, +} +unsafe impl Send for Packed {} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Packed; + +fn main() { + let mut x = 123; + + let p = Packed { + a: &mut x as *mut i32, + b: 456, + }; + + // When the structure was packed, the closure captures `p` which is Send. + // When `packed` is removed, this ends up capturing `p.a` which is not Send. + std::thread::spawn(move || unsafe { + *(p.a) += 1; // Error: cannot be sent between threads safely + }); +} +``` + +#### Major: Changing the value N of `repr(packed(N))` if that changes the alignment or layout {#repr-packed-n-change} + +It is a breaking change to change the value of N of `repr(packed(N))` if that changes the alignment or layout. +This may change the alignment or layout that external crates are relying on. + +If the value `N` is lowered below the alignment of a public field, then that would break any code that attempts to take a reference of that field. + +Note that some changes to `N` may not change the alignment or layout, for example increasing it when the current value is already equal to the natural alignment of the type. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(packed(4))] +pub struct Packed { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(packed(2))] // changed to 2 +pub struct Packed { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Packed; + +fn main() { + let p = Packed { a: 1, b: 2 }; + let x = &p.b; // Error: reference to packed field is unaligned +} +``` + +#### Major: Changing the value N of `repr(align(N))` if that changes the alignment {#repr-align-n-change} + +It is a breaking change to change the value `N` of `repr(align(N))` if that changes the alignment. +This may change the alignment that external crates are relying on. + +This change should be safe to make if the type is not well-defined as discussed in [type layout](#type-layout) (such as having any private fields and having an undocumented alignment or layout). + +Note that some changes to `N` may not change the alignment or layout, for example decreasing it when the current value is already equal to or less than the natural alignment of the type. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(align(8))] +pub struct Packed { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(align(4))] // changed to 4 +pub struct Packed { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Packed; + +fn main() { + let p = Packed { a: 1, b: 2 }; + // Some assumption about the size of the type. + // The alignment has changed from 8 to 4. + const _: () = assert!(std::mem::align_of::() == 8); // Error: evaluation of constant value failed +} +``` + +#### Major: Removing `repr(align)` from a struct, union, or enum {#repr-align-remove} + +It is a breaking change to remove `repr(align)` from a struct, union, or enum, if their layout was well-defined. +This may change the alignment or layout that external crates are relying on. + +This change should be safe to make if the type is not well-defined as discussed in [type layout](#type-layout) (such as having any private fields and having an undocumented alignment). + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(C, align(8))] +pub struct Packed { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(C)] // removed align +pub struct Packed { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Packed; + +fn main() { + let p = Packed { a: 1, b: 2 }; + // Some assumption about the size of the type. + // The alignment has changed from 8 to 4. + const _: () = assert!(std::mem::align_of::() == 8); // Error: evaluation of constant value failed +} +``` + +#### Major: Changing the order of public fields of a `repr(C)` type {#repr-c-shuffle} + +It is a breaking change to change the order of public fields of a `repr(C)` type. +External crates may be relying on the specific ordering of the fields. + +```rust,ignore,run-fail +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(C)] +pub struct SpecificLayout { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(C)] +pub struct SpecificLayout { + pub b: u32, // changed order + pub a: u8, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::SpecificLayout; + +extern "C" { + // This C function is assuming a specific layout defined in a C header. + fn c_fn_get_b(x: &SpecificLayout) -> u32; +} + +fn main() { + let p = SpecificLayout { a: 1, b: 2 }; + unsafe { assert_eq!(c_fn_get_b(&p), 2) } // Error: value not equal to 2 +} + +# mod cdep { +# // This simulates what would normally be something included from a build script. +# // This definition would be in a C header. +# #[repr(C)] +# pub struct SpecificLayout { +# pub a: u8, +# pub b: u32, +# } +# +# #[no_mangle] +# pub fn c_fn_get_b(x: &SpecificLayout) -> u32 { +# x.b +# } +# } +``` + +#### Major: Removing `repr(C)` from a struct, union, or enum {#repr-c-remove} + +It is a breaking change to remove `repr(C)` from a struct, union, or enum. +External crates may be relying on the specific layout of the type. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(C)] +pub struct SpecificLayout { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// After +// removed repr(C) +pub struct SpecificLayout { + pub a: u8, + pub b: u32, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::SpecificLayout; + +extern "C" { + // This C function is assuming a specific layout defined in a C header. + fn c_fn_get_b(x: &SpecificLayout) -> u32; // Error: is not FFI-safe +} + +fn main() { + let p = SpecificLayout { a: 1, b: 2 }; + unsafe { assert_eq!(c_fn_get_b(&p), 2) } +} + +# mod cdep { +# // This simulates what would normally be something included from a build script. +# // This definition would be in a C header. +# #[repr(C)] +# pub struct SpecificLayout { +# pub a: u8, +# pub b: u32, +# } +# +# #[no_mangle] +# pub fn c_fn_get_b(x: &SpecificLayout) -> u32 { +# x.b +# } +# } +``` + +#### Major: Removing `repr()` from an enum {#repr-int-enum-remove} + +It is a breaking change to remove `repr()` from an enum. +External crates may be assuming that the discriminant is a specific size. +For example, [`std::mem::transmute`] of an enum may fail. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(u16)] +pub enum Example { + Variant1, + Variant2, + Variant3, +} + +/////////////////////////////////////////////////////////// +// After +// removed repr(u16) +pub enum Example { + Variant1, + Variant2, + Variant3, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. + +fn main() { + let e = updated_crate::Example::Variant2; + let i: u16 = unsafe { std::mem::transmute(e) }; // Error: cannot transmute between types of different sizes +} +``` + +#### Major: Changing the primitive representation of a `repr()` enum {#repr-int-enum-change} + +It is a breaking change to change the primitive representation of a `repr()` enum. +External crates may be assuming that the discriminant is a specific size. +For example, [`std::mem::transmute`] of an enum may fail. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(u16)] +pub enum Example { + Variant1, + Variant2, + Variant3, +} + +/////////////////////////////////////////////////////////// +// After +#[repr(u8)] // changed repr size +pub enum Example { + Variant1, + Variant2, + Variant3, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. + +fn main() { + let e = updated_crate::Example::Variant2; + let i: u16 = unsafe { std::mem::transmute(e) }; // Error: cannot transmute between types of different sizes +} +``` + +#### Major: Removing `repr(transparent)` from a struct or enum {#repr-transparent-remove} + +It is a breaking change to remove `repr(transparent)` from a struct or enum. +External crates may be relying on the type having the alignment, layout, or size of the transparent field. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[repr(transparent)] +pub struct Transparent(T); + +/////////////////////////////////////////////////////////// +// After +// removed repr +pub struct Transparent(T); + +/////////////////////////////////////////////////////////// +// Example usage that will break. +#![deny(improper_ctypes)] +use updated_crate::Transparent; + +extern "C" { + fn c_fn() -> Transparent; // Error: is not FFI-safe +} + +fn main() {} +``` + +### Major: adding a private struct field when all current fields are public {#struct-add-private-field-when-public} + +When a private field is added to a struct that previously had all public fields, +this will break any code that attempts to construct it with a [struct literal]. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo { + pub f1: i32, +} + +/////////////////////////////////////////////////////////// +// After +pub struct Foo { + pub f1: i32, + f2: i32, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + let x = updated_crate::Foo { f1: 123 }; // Error: cannot construct `Foo` +} +``` + +Mitigation strategies: +* Do not add new fields to all-public field structs. +* Mark structs as [`#[non_exhaustive]`][non_exhaustive] when first introducing + a struct to prevent users from using struct literal syntax, and instead + provide a constructor method and/or [Default] implementation. + +### Major: adding a public field when no private field exists {#struct-add-public-field-when-no-private} + +When a public field is added to a struct that has all public fields, this will +break any code that attempts to construct it with a [struct literal]. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo { + pub f1: i32, +} + +/////////////////////////////////////////////////////////// +// After +pub struct Foo { + pub f1: i32, + pub f2: i32, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + let x = updated_crate::Foo { f1: 123 }; // Error: missing field `f2` +} +``` + +Mitigation strategies: +* Do not add new fields to all-public field structs. +* Mark structs as [`#[non_exhaustive]`][non_exhaustive] when first introducing + a struct to prevent users from using struct literal syntax, and instead + provide a constructor method and/or [Default] implementation. + +### Minor: adding or removing private fields when at least one already exists {#struct-private-fields-with-private} + +It is safe to add or remove private fields from a struct when the struct +already has at least one private field. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[derive(Default)] +pub struct Foo { + f1: i32, +} + +/////////////////////////////////////////////////////////// +// After +#[derive(Default)] +pub struct Foo { + f2: f64, +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +fn main() { + // Cannot access private fields. + let x = updated_crate::Foo::default(); +} +``` + +This is safe because existing code cannot use a [struct literal] to construct +it, nor exhaustively match its contents. + +Note that for tuple structs, this is a **major change** if the tuple contains +public fields, and the addition or removal of a private field changes the +index of any public field. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[derive(Default)] +pub struct Foo(pub i32, i32); + +/////////////////////////////////////////////////////////// +// After +#[derive(Default)] +pub struct Foo(f64, pub i32, i32); + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + let x = updated_crate::Foo::default(); + let y = x.0; // Error: is private +} +``` + +### Minor: going from a tuple struct with all private fields (with at least one field) to a normal struct, or vice versa {#struct-tuple-normal-with-private} + +Changing a tuple struct to a normal struct (or vice-versa) is safe if all +fields are private. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[derive(Default)] +pub struct Foo(i32); + +/////////////////////////////////////////////////////////// +// After +#[derive(Default)] +pub struct Foo { + f1: i32, +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +fn main() { + // Cannot access private fields. + let x = updated_crate::Foo::default(); +} +``` + +This is safe because existing code cannot use a [struct literal] to construct +it, nor match its contents. + +### Major: adding new enum variants (without `non_exhaustive`) {#enum-variant-new} + +It is a breaking change to add a new enum variant if the enum does not use the +[`#[non_exhaustive]`][non_exhaustive] attribute. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub enum E { + Variant1, +} + +/////////////////////////////////////////////////////////// +// After +pub enum E { + Variant1, + Variant2, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + use updated_crate::E; + let x = E::Variant1; + match x { // Error: `E::Variant2` not covered + E::Variant1 => {} + } +} +``` + +Mitigation strategies: +* When introducing the enum, mark it as [`#[non_exhaustive]`][non_exhaustive] + to force users to use [wildcard patterns] to catch new variants. + +### Major: adding new fields to an enum variant {#enum-fields-new} + +It is a breaking change to add new fields to an enum variant because all +fields are public, and constructors and matching will fail to compile. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub enum E { + Variant1 { f1: i32 }, +} + +/////////////////////////////////////////////////////////// +// After +pub enum E { + Variant1 { f1: i32, f2: i32 }, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + use updated_crate::E; + let x = E::Variant1 { f1: 1 }; // Error: missing f2 + match x { + E::Variant1 { f1 } => {} // Error: missing f2 + } +} +``` + +Mitigation strategies: +* When introducing the enum, mark the variant as [`non_exhaustive`][non_exhaustive] + so that it cannot be constructed or matched without wildcards. + ```rust,ignore,skip + pub enum E { + #[non_exhaustive] + Variant1{f1: i32} + } + ``` +* When introducing the enum, use an explicit struct as a value, where you can + have control over the field visibility. + ```rust,ignore,skip + pub struct Foo { + f1: i32, + f2: i32, + } + pub enum E { + Variant1(Foo) + } + ``` + +### Major: adding a non-defaulted trait item {#trait-new-item-no-default} + +It is a breaking change to add a non-defaulted item to a trait. This will +break any implementors of the trait. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub trait Trait {} + +/////////////////////////////////////////////////////////// +// After +pub trait Trait { + fn foo(&self); +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Trait; +struct Foo; + +impl Trait for Foo {} // Error: not all trait items implemented +``` + +Mitigation strategies: +* Always provide a default implementation or value for new associated trait + items. +* When introducing the trait, use the [sealed trait] technique to prevent + users outside of the crate from implementing the trait. + +### Major: any change to trait item signatures {#trait-item-signature} + +It is a breaking change to make any change to a trait item signature. This can +break external implementors of the trait. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub trait Trait { + fn f(&self, x: i32) {} +} + +/////////////////////////////////////////////////////////// +// After +pub trait Trait { + // For sealed traits or normal functions, this would be a minor change + // because generalizing with generics strictly expands the possible uses. + // But in this case, trait implementations must use the same signature. + fn f(&self, x: V) {} +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Trait; +struct Foo; + +impl Trait for Foo { + fn f(&self, x: i32) {} // Error: trait declaration has 1 type parameter +} +``` + +Mitigation strategies: +* Introduce new items with default implementations to cover the new + functionality instead of modifying existing items. +* When introducing the trait, use the [sealed trait] technique to prevent + users outside of the crate from implementing the trait. + +### Possibly-breaking: adding a defaulted trait item {#trait-new-default-item} + +It is usually safe to add a defaulted trait item. However, this can sometimes +cause a compile error. For example, this can introduce an ambiguity if a +method of the same name exists in another trait. + +```rust,ignore +// Breaking change example + +/////////////////////////////////////////////////////////// +// Before +pub trait Trait {} + +/////////////////////////////////////////////////////////// +// After +pub trait Trait { + fn foo(&self) {} +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Trait; +struct Foo; + +trait LocalTrait { + fn foo(&self) {} +} + +impl Trait for Foo {} +impl LocalTrait for Foo {} + +fn main() { + let x = Foo; + x.foo(); // Error: multiple applicable items in scope +} +``` + +Note that this ambiguity does *not* exist for name collisions on [inherent +implementations], as they take priority over trait items. + +See [trait-object-safety](#trait-object-safety) for a special case to consider +when adding trait items. + +Mitigation strategies: +* Some projects may deem this acceptable breakage, particularly if the new + item name is unlikely to collide with any existing code. Choose names + carefully to help avoid these collisions. Additionally, it may be acceptable + to require downstream users to add [disambiguation syntax] to select the + correct function when updating the dependency. + +### Major: adding a trait item that makes the trait non-object safe {#trait-object-safety} + +It is a breaking change to add a trait item that changes the trait to not be +[object safe]. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub trait Trait {} + +/////////////////////////////////////////////////////////// +// After +pub trait Trait { + // An associated const makes the trait not object-safe. + const CONST: i32 = 123; +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Trait; +struct Foo; + +impl Trait for Foo {} + +fn main() { + let obj: Box = Box::new(Foo); // Error: the trait `Trait` is not dyn compatible +} +``` + +It is safe to do the converse (making a non-object safe trait into a safe +one). + +### Major: adding a type parameter without a default {#trait-new-parameter-no-default} + +It is a breaking change to add a type parameter without a default to a trait. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub trait Trait {} + +/////////////////////////////////////////////////////////// +// After +pub trait Trait {} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Trait; +struct Foo; + +impl Trait for Foo {} // Error: missing generics +``` + +Mitigating strategies: +* See [adding a defaulted trait type parameter](#trait-new-parameter-default). + +### Minor: adding a defaulted trait type parameter {#trait-new-parameter-default} + +It is safe to add a type parameter to a trait as long as it has a default. +External implementors will use the default without needing to specify the +parameter. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub trait Trait {} + +/////////////////////////////////////////////////////////// +// After +pub trait Trait {} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +use updated_crate::Trait; +struct Foo; + +impl Trait for Foo {} +``` + +### Possibly-breaking change: adding any inherent items {#impl-item-new} + +Usually adding inherent items to an implementation should be safe because +inherent items take priority over trait items. However, in some cases the +collision can cause problems if the name is the same as an implemented trait +item with a different signature. + +```rust,ignore +// Breaking change example + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo; + +/////////////////////////////////////////////////////////// +// After +pub struct Foo; + +impl Foo { + pub fn foo(&self) {} +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Foo; + +trait Trait { + fn foo(&self, x: i32) {} +} + +impl Trait for Foo {} + +fn main() { + let x = Foo; + x.foo(1); // Error: this method takes 0 arguments but 1 argument was supplied +} +``` + +Note that if the signatures match, there would not be a compile-time error, +but possibly a silent change in runtime behavior (because it is now executing +a different function). + +Mitigation strategies: +* Some projects may deem this acceptable breakage, particularly if the new + item name is unlikely to collide with any existing code. Choose names + carefully to help avoid these collisions. Additionally, it may be acceptable + to require downstream users to add [disambiguation syntax] to select the + correct function when updating the dependency. + +### Major: tightening generic bounds {#generic-bounds-tighten} + +It is a breaking change to tighten generic bounds on a type since this can +break users expecting the looser bounds. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo { + pub f1: A, +} + +/////////////////////////////////////////////////////////// +// After +pub struct Foo { + pub f1: A, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Foo; + +fn main() { + let s = Foo { f1: 1.23 }; // Error: the trait bound `{float}: Eq` is not satisfied +} +``` + +### Minor: loosening generic bounds {#generic-bounds-loosen} + +It is safe to loosen the generic bounds on a type, as it only expands what is +allowed. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo { + pub f1: A, +} + +/////////////////////////////////////////////////////////// +// After +pub struct Foo { + pub f1: A, +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +use updated_crate::Foo; + +fn main() { + let s = Foo { f1: 123 }; +} +``` + +### Minor: adding defaulted type parameters {#generic-new-default} + +It is safe to add a type parameter to a type as long as it has a default. All +existing references will use the default without needing to specify the +parameter. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#[derive(Default)] +pub struct Foo {} + +/////////////////////////////////////////////////////////// +// After +#[derive(Default)] +pub struct Foo { + f1: A, +} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +use updated_crate::Foo; + +fn main() { + let s: Foo = Default::default(); +} +``` + +### Minor: generalizing a type to use generics (with identical types) {#generic-generalize-identical} + +A struct or enum field can change from a concrete type to a generic type +parameter, provided that the change results in an identical type for all +existing use cases. For example, the following change is permitted: + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo(pub u8); + +/////////////////////////////////////////////////////////// +// After +pub struct Foo(pub T); + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +use updated_crate::Foo; + +fn main() { + let s: Foo = Foo(123); +} +``` + +because existing uses of `Foo` are shorthand for `Foo` which yields the +identical field type. + +### Major: generalizing a type to use generics (with possibly different types) {#generic-generalize-different} + +Changing a struct or enum field from a concrete type to a generic type +parameter can break if the type can change. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo(pub T, pub u8); + +/////////////////////////////////////////////////////////// +// After +pub struct Foo(pub T, pub T); + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::Foo; + +fn main() { + let s: Foo = Foo(3.14, 123); // Error: mismatched types +} +``` + +### Minor: changing a generic type to a more generic type {#generic-more-generic} + +It is safe to change a generic type to a more generic one. For example, the +following adds a generic parameter that defaults to the original type, which +is safe because all existing users will be using the same type for both +fields, the defaulted parameter does not need to be specified. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo(pub T, pub T); + +/////////////////////////////////////////////////////////// +// After +pub struct Foo(pub T, pub U); + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +use updated_crate::Foo; + +fn main() { + let s: Foo = Foo(1.0, 2.0); +} +``` + +### Major: capturing more generic parameters in RPIT {#generic-rpit-capture} + +It is a breaking change to capture additional generic parameters in an [RPIT] (return-position impl trait). + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub fn f<'a, 'b>(x: &'a str, y: &'b str) -> impl Iterator + use<'a> { + x.chars() +} + +/////////////////////////////////////////////////////////// +// After +pub fn f<'a, 'b>(x: &'a str, y: &'b str) -> impl Iterator + use<'a, 'b> { + x.chars().chain(y.chars()) +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + let a = String::new(); + let b = String::new(); + let iter = updated_crate::f(&a, &b); + drop(b); // Error: cannot move out of `b` because it is borrowed +} +``` + +Adding generic parameters to an RPIT places additional constraints on how the resulting type may be used. + +Note that there are implicit captures when the `use<>` syntax is not specified. In Rust 2021 and earlier editions, the lifetime parameters are only captured if they appear syntactically within a bound in the RPIT type signature. Starting in Rust 2024, all lifetime parameters are unconditionally captured. This means that starting in Rust 2024, the default is maximally compatible, requiring you to be explicit when you want to capture less, which is a SemVer commitment. + +See the [edition guide][rpit-capture-guide] and the [reference][rpit-reference] for more information on RPIT capturing. + +It is a minor change to capture fewer generic parameters in an RPIT. + +> Note: All in-scope type and const generic parameters must be either implicitly captured (no `+ use<…>` specified) or explicitly captured (must be listed in `+ use<…>`), and thus currently it is not allowed to change what is captured of those kinds of generics. + +[RPIT]: ../../reference/types/impl-trait.md#abstract-return-types +[rpit-capture-guide]: ../../edition-guide/rust-2024/rpit-lifetime-capture.html +[rpit-reference]: ../../reference/types/impl-trait.md#capturing + +### Major: adding/removing function parameters {#fn-change-arity} + +Changing the arity of a function is a breaking change. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// After +pub fn foo(x: i32) {} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +fn main() { + updated_crate::foo(); // Error: this function takes 1 argument +} +``` + +Mitigating strategies: +* Introduce a new function with the new signature and possibly + [deprecate][deprecated] the old one. +* Introduce functions that take a struct argument, where the struct is built + with the builder pattern. This allows new fields to be added to the struct + in the future. + +### Possibly-breaking: introducing a new function type parameter {#fn-generic-new} + +Usually, adding a non-defaulted type parameter is safe, but in some +cases it can be a breaking change: + +```rust,ignore +// Breaking change example + +/////////////////////////////////////////////////////////// +// Before +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// After +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::foo; + +fn main() { + foo::(); // Error: function takes 2 generic arguments but 1 generic argument was supplied +} +``` + +However, such explicit calls are rare enough (and can usually be written in +other ways) that this breakage is usually acceptable. One should take into +account how likely it is that the function in question is being called with +explicit type arguments. + +### Minor: generalizing a function to use generics (supporting original type) {#fn-generalize-compatible} + +The type of a parameter to a function, or its return value, can be +*generalized* to use generics, including by introducing a new type parameter, +as long as it can be instantiated to the original type. For example, the +following changes are allowed: + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub fn foo(x: u8) -> u8 { + x +} +pub fn bar>(t: T) {} + +/////////////////////////////////////////////////////////// +// After +use std::ops::Add; +pub fn foo(x: T) -> T { + x +} +pub fn bar>(t: T) {} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +use updated_crate::{bar, foo}; + +fn main() { + foo(1); + bar(vec![1, 2, 3].into_iter()); +} +``` + +because all existing uses are instantiations of the new signature. + +Perhaps somewhat surprisingly, generalization applies to trait objects as +well, given that every trait implements itself: + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub trait Trait {} +pub fn foo(t: &dyn Trait) {} + +/////////////////////////////////////////////////////////// +// After +pub trait Trait {} +pub fn foo(t: &T) {} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. +use updated_crate::{foo, Trait}; + +struct Foo; +impl Trait for Foo {} + +fn main() { + let obj = Foo; + foo(&obj); +} +``` + +(The use of `?Sized` is essential; otherwise you couldn't recover the original +signature.) + +Introducing generics in this way can potentially create type inference +failures. These are usually rare, and may be acceptable breakage for some +projects, as this can be fixed with additional type annotations. + +```rust,ignore +// Breaking change example + +/////////////////////////////////////////////////////////// +// Before +pub fn foo() -> i32 { + 0 +} + +/////////////////////////////////////////////////////////// +// After +pub fn foo() -> T { + Default::default() +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::foo; + +fn main() { + let x = foo(); // Error: type annotations needed +} +``` + +### Major: generalizing a function to use generics with type mismatch {#fn-generalize-mismatch} + +It is a breaking change to change a function parameter or return type if the +generic type constrains or changes the types previously allowed. For example, +the following adds a generic constraint that may not be satisfied by existing +code: + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub fn foo(x: Vec) {} + +/////////////////////////////////////////////////////////// +// After +pub fn foo>(x: T) {} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::foo; + +fn main() { + foo(vec![1, 2, 3]); // Error: `Copy` is not implemented for `Vec` +} +``` + +### Minor: making an `unsafe` function safe {#fn-unsafe-safe} + +A previously `unsafe` function can be made safe without breaking code. + +Note however that it may cause the [`unused_unsafe`][unused_unsafe] lint to +trigger as in the example below, which will cause local crates that have +specified `#![deny(warnings)]` to stop compiling. Per [introducing new +lints](#new-lints), it is allowed for updates to introduce new warnings. + +Going the other way (making a safe function `unsafe`) is a breaking change. + +```rust,ignore +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub unsafe fn foo() {} + +/////////////////////////////////////////////////////////// +// After +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// Example use of the library that will trigger a lint. +use updated_crate::foo; + +unsafe fn bar(f: unsafe fn()) { + f() +} + +fn main() { + unsafe { foo() }; // The `unused_unsafe` lint will trigger here + unsafe { bar(foo) }; +} +``` + +Making a previously `unsafe` associated function or method on structs / enums +safe is also a minor change, while the same is not true for associated +function on traits (see [any change to trait item signatures](#trait-item-signature)). + +### Major: switching from `no_std` support to requiring `std` {#attr-no-std-to-std} + +If your library specifically supports a [`no_std`] environment, it is a +breaking change to make a new release that requires `std`. + +```rust,ignore,skip +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +#![no_std] +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// After +pub fn foo() { + std::time::SystemTime::now(); +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +// This will fail to link for no_std targets because they don't have a `std` crate. +#![no_std] +use updated_crate::foo; + +fn example() { + foo(); +} +``` + +Mitigation strategies: +* A common idiom to avoid this is to include a `std` [Cargo feature] that + optionally enables `std` support, and when the feature is off, the library + can be used in a `no_std` environment. + +### Major: adding `non_exhaustive` to an existing enum, variant, or struct with no private fields {#attr-adding-non-exhaustive} + +Making items [`#[non_exhaustive]`][non_exhaustive] changes how they may +be used outside the crate where they are defined: + +- Non-exhaustive structs and enum variants cannot be constructed + using [struct literal] syntax, including [functional update syntax]. +- Pattern matching on non-exhaustive structs requires `..` and + matching on enums does not count towards exhaustiveness. +- Casting enum variants to their discriminant with `as` is not allowed. + +Structs with private fields cannot be constructed using [struct literal] syntax +regardless of whether [`#[non_exhaustive]`][non_exhaustive] is used. +Adding [`#[non_exhaustive]`][non_exhaustive] to such a struct is not +a breaking change. + +```rust,ignore +// MAJOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub struct Foo { + pub bar: usize, +} + +pub enum Bar { + X, + Y(usize), + Z { a: usize }, +} + +pub enum Quux { + Var, +} + +/////////////////////////////////////////////////////////// +// After +#[non_exhaustive] +pub struct Foo { + pub bar: usize, +} + +pub enum Bar { + #[non_exhaustive] + X, + + #[non_exhaustive] + Y(usize), + + #[non_exhaustive] + Z { a: usize }, +} + +#[non_exhaustive] +pub enum Quux { + Var, +} + +/////////////////////////////////////////////////////////// +// Example usage that will break. +use updated_crate::{Bar, Foo, Quux}; + +fn main() { + let foo = Foo { bar: 0 }; // Error: cannot create non-exhaustive struct using struct expression + + let bar_x = Bar::X; // Error: unit variant `X` is private + let bar_y = Bar::Y(0); // Error: tuple variant `Y` is private + let bar_z = Bar::Z { a: 0 }; // Error: cannot create non-exhaustive variant using struct expression + + let q = Quux::Var; + match q { + Quux::Var => 0, + // Error: non-exhaustive patterns: `_` not covered + }; +} +``` + +Mitigation strategies: +* Mark structs, enums, and enum variants as + [`#[non_exhaustive]`][non_exhaustive] when first introducing them, + rather than adding [`#[non_exhaustive]`][non_exhaustive] later on. + +## Tooling and environment compatibility + +### Possibly-breaking: changing the minimum version of Rust required {#env-new-rust} + +Introducing the use of new features in a new release of Rust can break +projects that are using older versions of Rust. This also includes using new +features in a new release of Cargo, and requiring the use of a nightly-only +feature in a crate that previously worked on stable. + +It is generally recommended to treat this as a minor change, rather than as +a major change, for [various reasons][msrv-is-minor]. It +is usually relatively easy to update to a newer version of Rust. Rust also has +a rapid 6-week release cycle, and some projects will provide compatibility +within a window of releases (such as the current stable release plus N +previous releases). Just keep in mind that some large projects may not be able +to update their Rust toolchain rapidly. + +Mitigation strategies: +* Use [Cargo features] to make the new features opt-in. +* Provide a large window of support for older releases. +* Copy the source of new standard library items if possible so that you + can continue to use an older version but take advantage of the new feature. +* Provide a separate branch of older minor releases that can receive backports + of important bugfixes. +* Keep an eye out for the [`[cfg(version(..))]`][cfg-version] and + [`#[cfg(accessible(..))]`][cfg-accessible] features which provide an opt-in + mechanism for new features. These are currently unstable and only available + in the nightly channel. + +### Possibly-breaking: changing the platform and environment requirements {#env-change-requirements} + +There is a very wide range of assumptions a library makes about the +environment that it runs in, such as the host platform, operating system +version, available services, filesystem support, etc. It can be a breaking +change if you make a new release that restricts what was previously supported, +for example requiring a newer version of an operating system. These changes +can be difficult to track, since you may not always know if a change breaks in +an environment that is not automatically tested. + +Some projects may deem this acceptable breakage, particularly if the breakage +is unlikely for most users, or the project doesn't have the resources to +support all environments. Another notable situation is when a vendor +discontinues support for some hardware or OS, the project may deem it +reasonable to also discontinue support. + +Mitigation strategies: +* Document the platforms and environments you specifically support. +* Test your code on a wide range of environments in CI. + +### Minor: introducing new lints {#new-lints} + +Some changes to a library may cause new lints to be triggered in users of that library. +This should generally be considered a compatible change. + +```rust,ignore,dont-deny +// MINOR CHANGE + +/////////////////////////////////////////////////////////// +// Before +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// After +#[deprecated] +pub fn foo() {} + +/////////////////////////////////////////////////////////// +// Example use of the library that will safely work. + +fn main() { + updated_crate::foo(); // Warning: use of deprecated function +} +``` + +Beware that it may be possible for this to technically cause a project to fail if they have explicitly denied the warning, and the updated crate is a direct dependency. +Denying warnings should be done with care and the understanding that new lints may be introduced over time. +However, library authors should be cautious about introducing new warnings and may want to consider the potential impact on their users. + +The following lints are examples of those that may be introduced when updating a dependency: + +* [`deprecated`][deprecated-lint] --- Introduced when a dependency adds the [`#[deprecated]` attribute][deprecated] to an item you are using. +* [`unused_must_use`] --- Introduced when a dependency adds the [`#[must_use]` attribute][must-use-attr] to an item where you are not consuming the result. +* [`unused_unsafe`] --- Introduced when a dependency *removes* the `unsafe` qualifier from a function, and that is the only unsafe function called in an unsafe block. + +Additionally, updating `rustc` to a new version may introduce new lints. + +Transitive dependencies which introduce new lints should not usually cause a failure because Cargo uses [`--cap-lints`](../../rustc/lints/levels.html#capping-lints) to suppress all lints in dependencies. + +Mitigating strategies: +* If you build with warnings denied, understand you may need to deal with resolving new warnings whenever you update your dependencies. + If using RUSTFLAGS to pass `-Dwarnings`, also add the `-A` flag to allow lints that are likely to cause issues, such as `-Adeprecated`. +* Introduce deprecations behind a [feature][Cargo features]. + For example `#[cfg_attr(feature = "deprecated", deprecated="use bar instead")]`. + Then, when you plan to remove an item in a future SemVer breaking change, you can communicate with your users that they should enable the `deprecated` feature *before* updating to remove the use of the deprecated items. + This allows users to choose when to respond to deprecations without needing to immediately respond to them. + A downside is that it can be difficult to communicate to users that they need to take these manual steps to prepare for a major update. + +[`unused_must_use`]: ../../rustc/lints/listing/warn-by-default.html#unused-must-use +[deprecated-lint]: ../../rustc/lints/listing/warn-by-default.html#deprecated +[must-use-attr]: ../../reference/attributes/diagnostics.html#the-must_use-attribute +[`unused_unsafe`]: ../../rustc/lints/listing/warn-by-default.html#unused-unsafe + +### Cargo + +#### Minor: adding a new Cargo feature {#cargo-feature-add} + +It is usually safe to add new [Cargo features]. If the feature introduces new +changes that cause a breaking change, this can cause difficulties for projects +that have stricter backwards-compatibility needs. In that scenario, avoid +adding the feature to the "default" list, and possibly document the +consequences of enabling the feature. + +```toml +# MINOR CHANGE + +########################################################### +# Before +[features] +# ..empty + +########################################################### +# After +[features] +std = [] +``` + +#### Major: removing a Cargo feature {#cargo-feature-remove} + +It is usually a breaking change to remove [Cargo features]. This will cause +an error for any project that enabled the feature. + +```toml +# MAJOR CHANGE + +########################################################### +# Before +[features] +logging = [] + +########################################################### +# After +[dependencies] +# ..logging removed +``` + +Mitigation strategies: +* Clearly document your features. If there is an internal or experimental + feature, mark it as such, so that users know the status of the feature. +* Leave the old feature in `Cargo.toml`, but otherwise remove its + functionality. Document that the feature is deprecated, and remove it in a + future major SemVer release. + +#### Major: removing a feature from a feature list if that changes functionality or public items {#cargo-feature-remove-another} + +If removing a feature from another feature, this can break existing users if +they are expecting that functionality to be available through that feature. + +```toml +# Breaking change example + +########################################################### +# Before +[features] +default = ["std"] +std = [] + +########################################################### +# After +[features] +default = [] # This may cause packages to fail if they are expecting std to be enabled. +std = [] +``` + +#### Possibly-breaking: removing an optional dependency {#cargo-remove-opt-dep} + +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 + +########################################################### +# Before +[dependencies] +curl = { version = "0.4.31", optional = true } + +########################################################### +# After +[dependencies] +# ..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. +* Leave the optional dependency, and just don't use it within your library. +* Replace the optional dependency with a [Cargo feature] that does nothing, + and document that it is deprecated. +* Use high-level features which enable optional dependencies, and document + those as the preferred way to enable the extended functionality. For + example, if your library has optional support for something like + "networking", create a generic feature name "networking" that enables the + 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 +feature does not introduce a breaking change. + +```toml +# MINOR CHANGE + +########################################################### +# Before +[dependencies] +rand = { version = "0.7.3", features = ["small_rng"] } + + +########################################################### +# After +[dependencies] +rand = "0.7.3" +``` + +#### Minor: adding dependencies {#cargo-dep-add} + +It is usually safe to add new dependencies, as long as the new dependency +does not introduce new requirements that result in a breaking change. +For example, adding a new dependency that requires nightly in a project +that previously worked on stable is a major change. + +```toml +# MINOR CHANGE + +########################################################### +# Before +[dependencies] +# ..empty + +########################################################### +# After +[dependencies] +log = "0.4.11" +``` + +## Application compatibility + +Cargo projects may also include executable binaries which have their own +interfaces (such as a CLI interface, OS-level interaction, etc.). Since these +are part of the Cargo package, they often use and share the same version as +the package. You will need to decide if and how you want to employ a SemVer +contract with your users in the changes you make to your application. The +potential breaking and compatible changes to an application are too numerous +to list, so you are encouraged to use the spirit of the [SemVer] spec to guide +your decisions on how to apply versioning to your application, or at least +document what your commitments are. + +[`cfg` attribute]: ../../reference/conditional-compilation.md#the-cfg-attribute +[`no_std`]: ../../reference/names/preludes.html#the-no_std-attribute +[`pub use`]: ../../reference/items/use-declarations.html +[Cargo feature]: features.md +[Cargo features]: features.md +[cfg-accessible]: https://github.com/rust-lang/rust/issues/64797 +[cfg-version]: https://github.com/rust-lang/rust/issues/64796 +[conditional compilation]: ../../reference/conditional-compilation.md +[Default]: ../../std/default/trait.Default.html +[deprecated]: ../../reference/attributes/diagnostics.html#the-deprecated-attribute +[disambiguation syntax]: ../../reference/expressions/call-expr.html#disambiguating-function-calls +[functional update syntax]: ../../reference/expressions/struct-expr.html#functional-update-syntax +[inherent implementations]: ../../reference/items/implementations.html#inherent-implementations +[items]: ../../reference/items.html +[non_exhaustive]: ../../reference/attributes/type_system.html#the-non_exhaustive-attribute +[object safe]: ../../reference/items/traits.html#object-safety +[rust-feature]: https://doc.rust-lang.org/nightly/unstable-book/ +[sealed trait]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed +[SemVer]: https://semver.org/ +[struct literal]: ../../reference/expressions/struct-expr.html +[wildcard patterns]: ../../reference/patterns.html#wildcard-pattern +[unused_unsafe]: ../../rustc/lints/listing/warn-by-default.html#unused-unsafe +[msrv-is-minor]: https://github.com/rust-lang/api-guidelines/discussions/231 diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/source-replacement.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/source-replacement.md new file mode 100644 index 000000000..520604e5c --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/source-replacement.md @@ -0,0 +1,130 @@ +# Source Replacement + +This document is about replacing the crate index. You can read about overriding +dependencies in the [overriding dependencies] section of this +documentation. + +A *source* is a provider that contains crates that may be included as +dependencies for a package. Cargo supports the ability to **replace one source +with another** to express strategies such as: + +* Vendoring --- custom sources can be defined which represent crates on the local + filesystem. These sources are subsets of the source that they're replacing and + can be checked into packages if necessary. + +* Mirroring --- sources can be replaced with an equivalent version which acts as a + cache for crates.io itself. + +Cargo has a core assumption about source replacement that the source code is +exactly the same from both sources. Note that this also means that +a replacement source is not allowed to have crates which are not present in the +original source. + +As a consequence, source replacement is not appropriate for situations such as +patching a dependency or a private registry. Cargo supports patching +dependencies through the usage of [the `[patch]` key][overriding +dependencies], and private registry support is described in [the Registries +chapter][registries]. + +When using source replacement, running commands like `cargo publish` that need to +contact the registry require passing the `--registry` option. This helps avoid +any ambiguity about which registry to contact, and will use the authentication +token for the specified registry. + +[overriding dependencies]: overriding-dependencies.md +[registries]: registries.md + +## Configuration + +Configuration of replacement sources is done through [`.cargo/config.toml`][config] +and the full set of available keys are: + +```toml +# The `source` table is where all keys related to source-replacement +# are stored. +[source] + +# Under the `source` table are a number of other tables whose keys are a +# name for the relevant source. For example this section defines a new +# source, called `my-vendor-source`, which comes from a directory +# located at `vendor` relative to the directory containing this `.cargo/config.toml` +# file +[source.my-vendor-source] +directory = "vendor" + +# The crates.io default source for crates is available under the name +# "crates-io", and here we use the `replace-with` key to indicate that it's +# replaced with our source above. +# +# The `replace-with` key can also reference an alternative registry name +# defined in the `[registries]` table. +[source.crates-io] +replace-with = "my-vendor-source" + +# Each source has its own table where the key is the name of the source +[source.the-source-name] + +# Indicate that `the-source-name` will be replaced with `another-source`, +# defined elsewhere +replace-with = "another-source" + +# Several kinds of sources can be specified (described in more detail below): +registry = "https://example.com/path/to/index" +local-registry = "path/to/registry" +directory = "path/to/vendor" + +# Git sources can optionally specify a branch/tag/rev as well +git = "https://example.com/path/to/repo" +# branch = "master" +# tag = "v1.0.1" +# rev = "313f44e8" +``` + +[config]: config.md + +## 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 +[crates.io index](https://github.com/rust-lang/crates.io-index). That repository +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 + +A "local registry source" is intended to be a subset of another registry +source, but available on the local filesystem (aka vendoring). Local registries +are downloaded ahead of time, typically sync'd with a `Cargo.lock`, and are +made up of a set of `*.crate` files and an index like the normal registry is. + +The primary way to manage and create local registry sources is through the +[`cargo-local-registry`][cargo-local-registry] subcommand, +[available on crates.io][cargo-local-registry] and can be installed with +`cargo install cargo-local-registry`. + +[cargo-local-registry]: https://crates.io/crates/cargo-local-registry + +Local registries are contained within one directory and contain a number of +`*.crate` files downloaded from crates.io as well as an `index` directory with +the same format as the crates.io-index project (populated with just entries for +the crates that are present). + +## 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 +dependencies. Directory sources are primarily managed by the `cargo vendor` +subcommand. + +Directory sources are distinct from local registries though in that they contain +the unpacked version of `*.crate` files, making it more suitable in some +situations to check everything into source control. A directory source is just a +directory containing a number of other directories which contain the source code +for crates (the unpacked version of `*.crate` files). Currently no restriction +is placed on the name of each directory. + +Each crate in a directory source also has an associated metadata file indicating +the checksum of each file in the crate to protect against accidental +modifications. diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/specifying-dependencies.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/specifying-dependencies.md new file mode 100644 index 000000000..9f2bd5cb8 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/specifying-dependencies.md @@ -0,0 +1,675 @@ +# Specifying Dependencies + +Your crates can depend on other libraries from [crates.io] or other +registries, `git` repositories, or subdirectories on your local file system. +You can also temporarily override the location of a dependency --- for example, +to be able to test out a bug fix in the dependency that you are working on +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 + +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 +guide](../guide/index.md), we specified a dependency on the `time` crate: + +```toml +[dependencies] +time = "0.1.12" +``` + +The version string `"0.1.12"` is called a [version requirement](#version-requirement-syntax). +It specifies a range of versions that can be selected from when [resolving dependencies](resolver.md). +In this case, `"0.1.12"` represents the version range `>=0.1.12, <0.2.0`. +An update is allowed if it is within that range. +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`. + +## Version requirement syntax + +### Default requirements + +**Default requirements** specify a minimum version with the ability to update to [SemVer] compatible versions. +Versions are considered compatible if their left-most non-zero major/minor/patch component is the same. +This is different from [SemVer] which considers all pre-1.0.0 packages to be incompatible. + +`1.2.3` is an example of a default requirement. + +```notrust +1.2.3 := >=1.2.3, <2.0.0 +1.2 := >=1.2.0, <2.0.0 +1 := >=1.0.0, <2.0.0 +0.2.3 := >=0.2.3, <0.3.0 +0.2 := >=0.2.0, <0.3.0 +0.0.3 := >=0.0.3, <0.0.4 +0.0 := >=0.0.0, <0.1.0 +0 := >=0.0.0, <1.0.0 +``` + +### Caret requirements + +**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 + +**Tilde requirements** specify a minimal version with some ability to update. +If you specify a major, minor, and patch version or only a major and minor +version, only patch-level changes are allowed. If you only specify a major +version, then minor- and patch-level changes are allowed. + +`~1.2.3` is an example of a tilde requirement. + +```notrust +~1.2.3 := >=1.2.3, <1.3.0 +~1.2 := >=1.2.0, <1.3.0 +~1 := >=1.0.0, <2.0.0 +``` + +### Wildcard requirements + +**Wildcard requirements** allow for any version where the wildcard is +positioned. + +`*`, `1.*` and `1.2.*` are examples of wildcard requirements. + +```notrust +* := >=0.0.0 +1.* := >=1.0.0, <2.0.0 +1.2.* := >=1.2.0, <1.3.0 +``` + +> **Note**: [crates.io] does not allow bare `*` versions. + +### Comparison requirements + +**Comparison requirements** allow manually specifying a version range or an +exact version to depend on. + +Here are some examples of comparison requirements: + +```notrust +>= 1.2.0 +> 1 +< 2 += 1.2.3 +``` + + +### Multiple version requirements + +As shown in the examples above, multiple version requirements can be +separated with a comma, e.g., `>= 1.2, < 1.5`. + +### Pre-releases + +Version requirements exclude [pre-release versions](manifest.md#the-version-field), such as `1.0.0-alpha`, +unless specifically asked for. +For example, if `1.0.0-alpha` of package +`foo` is published, then a requirement of `foo = "1.0"` will *not* match, and +will return an error. The pre-release must be specified, such as `foo = +"1.0.0-alpha"`. +Similarly [`cargo install`] will avoid pre-releases unless +explicitly asked to install one. + +Cargo allows "newer" pre-releases to be used automatically. For example, if +`1.0.0-beta` is published, then a requirement `foo = "1.0.0-alpha"` will allow +updating to the `beta` version. Note that this only works on the same release +version, `foo = "1.0.0-alpha"` will not allow updating to `foo = "1.0.1-alpha"` +or `foo = "1.0.1-beta"`. + +Cargo will also upgrade automatically to semver-compatible released versions +from prereleases. The requirement `foo = "1.0.0-alpha"` will allow updating to +`foo = "1.0.0"` as well as `foo = "1.2.0"`. + +Beware that pre-release versions can be unstable, and as such care should be +taken when using them. Some projects may choose to publish breaking changes +between pre-release versions. It is recommended to not use pre-release +dependencies in a library if your library is not also a pre-release. Care +should also be taken when updating your `Cargo.lock`, and be prepared if a +pre-release update causes issues. + +[`cargo install`]: ../commands/cargo-install.md + +### Version metadata + +[Version metadata](manifest.md#the-version-field), such as `1.0.0+21AF26D3`, +is ignored and should not be used in version requirements. + +> **Recommendation:** When in doubt, use the default version requirement operator. +> +> In rare circumstances, a package with a "public dependency" +> (re-exports the dependency or interoperates with it in its public API) +> that is compatible with multiple semver-incompatible versions +> (e.g. only uses a simple type that hasn't changed between releases, like an `Id`) +> may support users choosing which version of the "public dependency" to use. +> In this case, a version requirement like `">=0.4, <2"` may be of interest. +> *However* users of the package will likely run into errors and need to +> manually select a version of the "public dependency" via `cargo update` if +> they also depend on it as Cargo might pick different versions of the "public +> dependency" when [resolving dependency versions](resolver.md) (see +> [#10599]). +> +> Avoid constraining the upper bound of a version to be anything less than the +> next semver incompatible version +> (e.g. avoid `">=2.0, <2.4"`) as other packages in the dependency tree may +> require a newer version, leading to an unresolvable error (see [#9029]). +> Consider whether controlling the version in your [`Cargo.lock`] would be more +> appropriate. +> +> In some instances this won't matter or the benefits might outweigh the cost, including: +> - When no one else depends on your package e.g. it only has a `[[bin]]` +> - When depending on a pre-release package and wishing to avoid breaking +> changes then a fully specified `"=1.2.3-alpha.3"` might be warranted (see +> [#2222]) +> - When a library re-exports a proc-macro but the proc-macro generates code that +> calls into the re-exporting library then a fully specified `=1.2.3` might be +> warranted to ensure the proc-macro isn't newer than the re-exporting library +> and generating code that uses parts of the API that don't exist within the +> current version + +[`Cargo.lock`]: ../guide/cargo-toml-vs-cargo-lock.md +[#2222]: https://github.com/rust-lang/cargo/issues/2222 +[#9029]: https://github.com/rust-lang/cargo/issues/9029 +[#10599]: https://github.com/rust-lang/cargo/issues/10599 + +## Specifying dependencies from other registries + +To specify a dependency from a registry other than [crates.io] set the `registry` key +to the name of the registry to use: + +```toml +[dependencies] +some-crate = { version = "1.0", registry = "my-registry" } +``` + +where `my-registry` is the registry name configured in `.cargo/config.toml` file. +See the [registries documentation] for more information. + +> **Note**: [crates.io] does not allow packages to be published with +> dependencies on code published outside of [crates.io]. + +[registries documentation]: registries.md + +## 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: + +```toml +[dependencies] +regex = { git = "https://github.com/rust-lang/regex.git" } +``` + +Cargo fetches the `git` repository at that location and traverses the file tree to find +`Cargo.toml` file for the requested crate anywhere inside the `git` repository. +For example, `regex-lite` and `regex-syntax` are members of `rust-lang/regex` repo +and can be referred to by the repo's root URL (`https://github.com/rust-lang/regex.git`) +regardless of where in the file tree they reside. + +```toml +regex-lite = { git = "https://github.com/rust-lang/regex.git" } +regex-syntax = { git = "https://github.com/rust-lang/regex.git" } +``` + +The above rule does not apply to [`path` dependencies](#specifying-path-dependencies). + +### Choice of commit + +Cargo assumes that we intend to use the latest commit on the default branch to build +our package if we only specify the repo URL, as in the examples above. + +You can combine the `git` key with the `rev`, `tag`, or `branch` keys to be more specific about +which commit to use. Here's an example of using the latest commit on a branch named `next`: + +```toml +[dependencies] +regex = { git = "https://github.com/rust-lang/regex.git", branch = "next" } +``` + +Anything that is not a branch or a tag falls under `rev` key. This can be a commit +hash like `rev = "4c59b707"`, or a named reference exposed by the remote +repository such as `rev = "refs/pull/493/head"`. + +What references are available for the `rev` key varies by where the repo is hosted. +GitHub exposes a reference to the most recent commit of every pull request as in the example above. +Other git hosts may provide something equivalent under a different naming scheme. + +**More `git` dependency examples:** + +```toml +# .git suffix can be omitted if the host accepts such URLs - both examples work the same +regex = { git = "https://github.com/rust-lang/regex" } +regex = { git = "https://github.com/rust-lang/regex.git" } + +# a commit with a particular tag +regex = { git = "https://github.com/rust-lang/regex.git", tag = "1.10.3" } + +# a commit by its SHA1 hash +regex = { git = "https://github.com/rust-lang/regex.git", rev = "0c0990399270277832fbb5b91a1fa118e6f63dba" } + +# HEAD commit of PR 493 +regex = { git = "https://github.com/rust-lang/regex.git", rev = "refs/pull/493/head" } + +# INVALID EXAMPLES + +# specifying the commit after # ignores the commit ID and generates a warning +regex = { git = "https://github.com/rust-lang/regex.git#4c59b70" } + +# git and path cannot be used at the same time +regex = { git = "https://github.com/rust-lang/regex.git#4c59b70", path = "../regex" } +``` + +Cargo locks the commits of `git` dependencies in `Cargo.lock` file at the time of their addition +and checks for updates only when you run `cargo update` command. + +### The role of the `version` key + +The `version` key always implies that the package is available in a registry, +regardless of the presence of `git` or `path` keys. + +The `version` key does _not_ affect which commit is used when Cargo retrieves the `git` dependency, +but Cargo checks the version information in the dependency's `Cargo.toml` file +against the `version` key and raises an error if the check fails. + +In this example, Cargo retrieves the HEAD commit of the branch called `next` from Git and checks if the crate's version +is compatible with `version = "1.10.3"`: + +```toml +[dependencies] +regex = { version = "1.10.3", git = "https://github.com/rust-lang/regex.git", branch = "next" } +``` + +`version`, `git`, and `path` keys are considered separate locations for resolving the dependency. +See [Multiple locations](#multiple-locations) section below for detailed explanations. + +> **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. + +### Accessing private Git repositories + +See [Git Authentication](../appendix/git-authentication.md) for help with Git authentication for private repos. + +## 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 +split out a separate crate for others to use. To do this Cargo supports **path +dependencies** which are typically sub-crates that live within one repository. +Let’s start by making a new crate inside of our `hello_world` package: + +```console +# inside of hello_world/ +$ cargo new hello_utils +``` + +This will create a new folder `hello_utils` inside of which a `Cargo.toml` and +`src` folder are ready to be configured. To tell Cargo about this, open +up `hello_world/Cargo.toml` and add `hello_utils` to your dependencies: + +```toml +[dependencies] +hello_utils = { path = "hello_utils" } +``` + +This tells Cargo that we depend on a crate called `hello_utils` which is found +in the `hello_utils` folder, relative to the `Cargo.toml` file it’s written in. + +The next `cargo build` will automatically build `hello_utils` and +all of its dependencies. + +### No local path traversal + +The local paths must point to the exact folder with the dependency's `Cargo.toml`. +Unlike with `git` dependencies, Cargo does not traverse local paths. +For example, if `regex-lite` and `regex-syntax` are members of a +locally cloned `rust-lang/regex` repo, they have to be referred to by the full path: + +```toml +# git key accepts the repo root URL and Cargo traverses the tree to find the crate +[dependencies] +regex-lite = { git = "https://github.com/rust-lang/regex.git" } +regex-syntax = { git = "https://github.com/rust-lang/regex.git" } + +# path key requires the member name to be included in the local path +[dependencies] +regex-lite = { path = "../regex/regex-lite" } +regex-syntax = { path = "../regex/regex-syntax" } +``` + +### Local paths in published crates + +Crates that use dependencies specified with only a path are not +permitted on [crates.io]. + +If we wanted to publish our `hello_world` crate, +we would need to publish a version of `hello_utils` to [crates.io] as a separate crate +and specify its version in the dependencies line of `hello_world`: + +```toml +[dependencies] +hello_utils = { path = "hello_utils", version = "0.1.0" } +``` + +The use of `path` and `version` keys together is explained in the [Multiple locations](#multiple-locations) section. + +> **Note**: [crates.io] does not allow packages to be published with +> dependencies on code outside of [crates.io], except for [dev-dependencies]. +> See the [Multiple locations](#multiple-locations) section +> for a fallback alternative for `git` and `path` dependencies. + +## 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 +the `version` is checked against the local copy), and when published to a +registry like [crates.io], it will use the registry version. Other +combinations are not allowed. Examples: + +```toml +[dependencies] +# Uses `my-bitflags` when used locally, and uses +# version 1.0 from crates.io when published. +bitflags = { path = "my-bitflags", version = "1.0" } + +# Uses the given git repo when used locally, and uses +# version 1.0 from crates.io when published. +smallvec = { git = "https://github.com/servo/rust-smallvec.git", version = "1.0" } + +# Note: if a version doesn't match, Cargo will fail to compile! +``` + +One example where this can be useful is when you have split up a library into +multiple packages within the same workspace. You can then use `path` +dependencies to point to the local packages within the workspace to use the +local version during development, and then use the [crates.io] version once it +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 take the same format, but are listed under a +`target` section. Normally Rust-like [`#[cfg]` +syntax](../../reference/conditional-compilation.html) will be used to define +these sections: + +```toml +[target.'cfg(windows)'.dependencies] +winhttp = "0.4.0" + +[target.'cfg(unix)'.dependencies] +openssl = "1.0.1" + +[target.'cfg(target_arch = "x86")'.dependencies] +native-i686 = { path = "native/i686" } + +[target.'cfg(target_arch = "x86_64")'.dependencies] +native-x86_64 = { path = "native/x86_64" } +``` + +Like with Rust, the syntax here supports the `not`, `any`, and `all` operators +to combine various cfg name/value pairs. + +If you want to know which cfg targets are available on your platform, run +`rustc --print=cfg` from the command line. If you want to know which `cfg` +targets are available for another platform, such as 64-bit Windows, +run `rustc --print=cfg --target=x86_64-pc-windows-msvc`. + +Unlike in your Rust source code, you cannot use +`[target.'cfg(feature = "fancy-feature")'.dependencies]` to add dependencies +based on optional features. Use [the `[features]` section](features.md) +instead: + +```toml +[dependencies] +foo = { version = "1.0", optional = true } +bar = { version = "1.0", optional = true } + +[features] +fancy-feature = ["foo", "bar"] +``` + +The same applies to `cfg(debug_assertions)`, `cfg(test)` and `cfg(proc_macro)`. +These values will not work as expected and will always have the default value +returned by `rustc --print=cfg`. +There is currently no way to add dependencies based on these configuration values. + +In addition to `#[cfg]` syntax, Cargo also supports listing out the full target +the dependencies would apply to: + +```toml +[target.x86_64-pc-windows-gnu.dependencies] +winhttp = "0.4.0" + +[target.i686-unknown-linux-gnu.dependencies] +openssl = "1.0.1" +``` + +### 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: + +```toml +[target.bar.dependencies] +winhttp = "0.4.0" + +[target.my-special-i686-platform.dependencies] +openssl = "1.0.1" +native = { path = "native/i686" } +``` + +> **Note**: Custom target specifications are not usable on the stable channel. + +## Development dependencies + +You can add a `[dev-dependencies]` section to your `Cargo.toml` whose format +is equivalent to `[dependencies]`: + +```toml +[dev-dependencies] +tempdir = "0.3" +``` + +Dev-dependencies are not used when compiling +a package for building, but are used for compiling tests, examples, and +benchmarks. + +These dependencies are *not* propagated to other packages which depend on this +package. + +You can also have target-specific development dependencies by using +`dev-dependencies` in the target section header instead of `dependencies`. For +example: + +```toml +[target.'cfg(unix)'.dev-dependencies] +mio = "0.0.1" +``` + +> **Note**: When a package is published, only dev-dependencies that specify a +> `version` will be included in the published crate. For most use cases, +> dev-dependencies are not needed when published, though some users (like OS +> packagers) may want to run tests within a crate, so providing a `version` if +> possible can still be beneficial. + +## 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 +manifest: + +```toml +[build-dependencies] +cc = "1.0.3" +``` + + +You can also have target-specific build dependencies by using +`build-dependencies` in the target section header instead of `dependencies`. For +example: + +```toml +[target.'cfg(unix)'.build-dependencies] +cc = "1.0.3" +``` + +In this case, the dependency will only be built when the host platform matches the +specified target. + +The build script **does not** have access to the dependencies listed +in the `dependencies` or `dev-dependencies` section. Build +dependencies will likewise not be available to the package itself +unless listed under the `dependencies` section as well. A package +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 + +If a package you depend on offers conditional features, you can +specify which to use: + +```toml +[dependencies.awesome] +version = "1.3.5" +default-features = false # do not include the default features, and optionally + # cherry-pick individual features +features = ["secure-password", "civet"] +``` + +More information about features can be found in the [features +chapter](features.md#dependency-features). + +## 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 +code. For some projects, though, you may wish to reference the crate with a +different name in the code regardless of how it's published on crates.io. For +example you may wish to: + +* Avoid the need to `use foo as bar` in Rust source. +* Depend on multiple versions of a crate. +* Depend on crates with the same name from different registries. + +To support this Cargo supports a `package` key in the `[dependencies]` section +of which package should be depended on: + +```toml +[package] +name = "mypackage" +version = "0.0.1" + +[dependencies] +foo = "0.1" +bar = { git = "https://github.com/example/project.git", package = "foo" } +baz = { version = "0.1", registry = "custom", package = "foo" } +``` + +In this example, three crates are now available in your Rust code: + +```rust,ignore +extern crate foo; // crates.io +extern crate bar; // git repository +extern crate baz; // registry `custom` +``` + +All three of these crates have the package name of `foo` in their own +`Cargo.toml`, so we're explicitly using the `package` key to inform Cargo that +we want the `foo` package even though we're calling it something else locally. +The `package` key, if not specified, defaults to the name of the dependency +being requested. + +Note that if you have an optional dependency like: + +```toml +[dependencies] +bar = { version = "0.1", package = 'foo', optional = true } +``` + +you're depending on the crate `foo` from crates.io, but your crate has a `bar` +feature instead of a `foo` feature. That is, names of features take after the +name of the dependency, not the package name, when renamed. + +Enabling transitive dependencies works similarly, for example we could add the +following to the above manifest: + +```toml +[features] +log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error! +``` + +## 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. +After that, add it to the `[dependencies]` table with `workspace = true`. + +Along with the `workspace` key, dependencies can also include these keys: +- [`optional`][optional]: Note that the`[workspace.dependencies]` table is not allowed to specify `optional`. +- [`features`][features]: These are additive with the features declared in the `[workspace.dependencies]` + +Other than `optional` and `features`, inherited dependencies cannot use any other +dependency key (such as `version` or `default-features`). + +Dependencies in the `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and +`[target."...".dependencies]` sections support the ability to reference the +`[workspace.dependencies]` definition of dependencies. + +```toml +[package] +name = "bar" +version = "0.2.0" + +[dependencies] +regex = { workspace = true, features = ["unicode"] } + +[build-dependencies] +cc.workspace = true + +[dev-dependencies] +rand = { workspace = true, optional = true } +``` + + +[SemVer]: https://semver.org +[crates.io]: https://crates.io/ +[dev-dependencies]: #development-dependencies +[workspace.dependencies]: workspaces.md#the-dependencies-table +[optional]: features.md#optional-dependencies +[features]: features.md + + diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/timings.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/timings.md new file mode 100644 index 000000000..e8ff751ca --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/timings.md @@ -0,0 +1,66 @@ +# Reporting build timings +The `--timings` option gives some information about how long each compilation +takes, and tracks concurrency information over time. + +```sh +cargo build --timings +``` + +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 + +There are two tables and two graphs in the output. + +The first table displays the build information of the project, including the +number of units built, the maximum number of concurrency, build time, and the +version information of the currently used compiler. + +![build-info](../images/build-info.png) + +The "unit" graph shows the duration of each unit over time. A "unit" is a single +compiler invocation. There are lines that show which additional units are +"unlocked" when a unit finishes. That is, it shows the new units that are now +allowed to run because their dependencies are all finished. Hover the mouse over +a unit to highlight the lines. This can help visualize the critical path of +dependencies. This may change between runs because the units may finish in +different orders. + +The "codegen" times are highlighted in a lavender color. In some cases, build +pipelining allows units to start when their dependencies are performing code +generation. This information is not always displayed (for example, binary +units do not show when code generation starts). + +The "custom build" units are `build.rs` scripts, which when run are +highlighted in orange. + +![build-unit-time](../images/build-unit-time.png) + +The second graph shows Cargo's concurrency over time. The background +indicates CPU usage. The three lines are: +- "Waiting" (red) --- This is the number of units waiting for a CPU slot to + open. +- "Inactive" (blue) --- This is the number of units that are waiting for their + dependencies to finish. +- "Active" (green) --- This is the number of units currently running. + +![cargo-concurrency-over-time](../images/cargo-concurrency-over-time.png) + +Note: This does not show the concurrency in the compiler itself. `rustc` +coordinates with Cargo via the "job server" to stay within the concurrency +limit. This currently mostly applies to the code generation phase. + +Tips for addressing compile times: +- Look for slow dependencies. + - Check if they have features that you may wish to consider disabling. + - Consider trying to remove the dependency completely. +- Look for a crate being built multiple times with different versions. Try to + remove the older versions from the dependency graph. +- Split large crates into smaller pieces. +- If there are a large number of crates bottlenecked on a single crate, focus + your attention on improving that one crate to improve parallelism. + +The last table lists the total time and "codegen" time spent on each unit, +as well as the features that were enabled during each unit's compilation. diff --git a/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/unstable.md b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/unstable.md new file mode 100644 index 000000000..3eba4e458 --- /dev/null +++ b/collector/compile-benchmarks/cargo-0.87.1/src/doc/src/reference/unstable.md @@ -0,0 +1,1995 @@ +# 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 +needs, and if there are any issues or problems. Check the linked tracking +issues listed below for more information on the feature, and click the GitHub +subscribe button if you want future updates. + +After some period of time, if the feature does not have any major concerns, it +can be [stabilized], which will make it available on stable once the current +nightly release reaches the stable channel (anywhere from 6 to 12 weeks). + +There are three different ways that unstable features can be enabled based on +how the feature works: + +* New syntax in `Cargo.toml` requires a `cargo-features` key at the top of + `Cargo.toml`, before any tables. For example: + + ```toml + # This specifies which new Cargo.toml features are enabled. + cargo-features = ["test-dummy-unstable"] + + [package] + name = "my-package" + version = "0.1.0" + im-a-teapot = true # This is a new option enabled by test-dummy-unstable. + ``` + +* New command-line flags, options, and subcommands require the `-Z + unstable-options` CLI option to also be included. For example, the new + `--artifact-dir` option is only available on nightly: + + ```cargo +nightly build --artifact-dir=out -Z unstable-options``` + +* `-Z` command-line flags are used to enable new functionality that may not + have an interface, or the interface has not yet been designed, or for more + complex features that affect multiple parts of Cargo. For example, the + [mtime-on-use](#mtime-on-use) feature can be enabled with: + + ```cargo +nightly build -Z mtime-on-use``` + + Run `cargo -Z help` to see a list of flags available. + + Anything which can be configured with a `-Z` flag can also be set in the + cargo [config file] (`.cargo/config.toml`) in the `unstable` table. For + example: + + ```toml + [unstable] + mtime-on-use = true + build-std = ["core", "alloc"] + ``` + +Each new feature described below should explain how to use it. + +*For the latest nightly, see the [nightly version] of this page.* + +[config file]: config.md +[nightly channel]: ../../book/appendix-07-nightly-rust.html +[stabilized]: https://doc.crates.io/contrib/process/unstable.html#stabilization +[nightly version]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html + +## List of unstable features + +* Unstable-specific features + * [-Z allow-features](#allow-features) --- Provides a way to restrict which unstable features are used. +* Build scripts and linking + * [Metabuild](#metabuild) --- Provides declarative build scripts. +* Resolver and features + * [no-index-update](#no-index-update) --- Prevents cargo from updating the index cache. + * [avoid-dev-deps](#avoid-dev-deps) --- Prevents the resolver from including dev-dependencies during resolution. + * [minimal-versions](#minimal-versions) --- Forces the resolver to use the lowest compatible version instead of the highest. + * [direct-minimal-versions](#direct-minimal-versions) — Forces the resolver to use the lowest compatible version instead of the highest. + * [public-dependency](#public-dependency) --- Allows dependencies to be classified as either public or private. + * [msrv-policy](#msrv-policy) --- MSRV-aware resolver and version selection + * [precise-pre-release](#precise-pre-release) --- Allows pre-release versions to be selected with `update --precise` + * [update-breaking](#update-breaking) --- Allows upgrading to breaking versions with `update --breaking` +* Output behavior + * [artifact-dir](#artifact-dir) --- Adds a directory where artifacts are copied to. + * [Different binary name](#different-binary-name) --- Assign a name to the built binary that is separate from the crate name. + * [root-dir](#root-dir) --- Controls the root directory relative to which paths are printed +* Compile behavior + * [mtime-on-use](#mtime-on-use) --- Updates the last-modified timestamp on every dependency every time it is used, to provide a mechanism to delete unused artifacts. + * [doctest-xcompile](#doctest-xcompile) --- Supports running doctests with the `--target` flag. + * [build-std](#build-std) --- Builds the standard library instead of using pre-built binaries. + * [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. + * [checksum-freshness](#checksum-freshness) --- When passed, the decision as to whether a crate needs to be rebuilt is made using file checksums instead of the file mtime. + * [panic-abort-tests](#panic-abort-tests) --- Allows running tests with the "abort" panic strategy. + * [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. + * [gc](#gc) --- Global cache garbage collection. + * [open-namespaces](#open-namespaces) --- Allow multiple packages to participate in the same API namespace +* rustdoc + * [rustdoc-map](#rustdoc-map) --- Provides mappings for documentation to link to external sites like [docs.rs](https://docs.rs/). + * [scrape-examples](#scrape-examples) --- Shows examples within documentation. + * [output-format](#output-format-for-rustdoc) --- Allows documentation to also be emitted in the experimental [JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). +* `Cargo.toml` extensions + * [Profile `rustflags` option](#profile-rustflags-option) --- Passed directly to rustc. + * [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. + * [Profile `trim-paths` option](#profile-trim-paths-option) --- Control the sanitization of file paths in build outputs. + * [`[lints.cargo]`](#lintscargo) --- Allows configuring lints for Cargo. + * [path bases](#path-bases) --- Named base directories for path dependencies. +* 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. + * [`cargo rustc --print`](#rustc---print) --- Calls rustc with `--print` to display information from rustc. +* Configuration + * [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 + * [publish-timeout](#publish-timeout) --- Controls the timeout between uploading the crate and being available in the index + * [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. + * [lockfile-path](#lockfile-path) --- Allows to specify a path to lockfile other than the default path `/Cargo.lock`. + * [package-workspace](#package-workspace) --- Allows for packaging and publishing multiple crates in a workspace. + * [native-completions](#native-completions) --- Move cargo shell completions to native completions. + * [warnings](#warnings) --- controls warning behavior; options for allowing or denying warnings. + +## allow-features + +This permanently-unstable flag makes it so that only a listed set of +unstable features can be used. Specifically, if you pass +`-Zallow-features=foo,bar`, you'll continue to be able to pass `-Zfoo` +and `-Zbar` to `cargo`, but you will be unable to pass `-Zbaz`. You can +pass an empty string (`-Zallow-features=`) to disallow all unstable +features. + +`-Zallow-features` also restricts which unstable features can be passed +to the `cargo-features` entry in `Cargo.toml`. If, for example, you want +to allow + +```toml +cargo-features = ["test-dummy-unstable"] +``` + +where `test-dummy-unstable` is unstable, that features would also be +disallowed by `-Zallow-features=`, and allowed with +`-Zallow-features=test-dummy-unstable`. + +The list of features passed to cargo's `-Zallow-features` is also passed +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 +* Original Issue: [#3479](https://github.com/rust-lang/cargo/issues/3479) +* Tracking Issue: [#7404](https://github.com/rust-lang/cargo/issues/7404) + +The `-Z no-index-update` flag ensures that Cargo does not attempt to update +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 +* 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) + +The `-Z mtime-on-use` flag is an experiment to have Cargo update the mtime of +used files to make it easier for tools like cargo-sweep to detect which files +are stale. For many workflows this needs to be set on *all* invocations of cargo. +To make this more practical setting the `unstable.mtime_on_use` flag in `.cargo/config.toml` +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 +* Original Issue: [#4988](https://github.com/rust-lang/cargo/issues/4988) +* Tracking Issue: [#5133](https://github.com/rust-lang/cargo/issues/5133) + +When running commands such as `cargo install` or `cargo build`, Cargo +currently requires dev-dependencies to be downloaded, even if they are not +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 +* Original Issue: [#4100](https://github.com/rust-lang/cargo/issues/4100) +* Tracking Issue: [#5657](https://github.com/rust-lang/cargo/issues/5657) + +> Note: It is not recommended to use this feature. Because it enforces minimal +> versions for all transitive dependencies, its usefulness is limited since +> not all external dependencies declare proper lower version bounds. It is +> intended that it will be changed in the future to only enforce minimal +> versions for direct dependencies. + +When a `Cargo.lock` file is generated, the `-Z minimal-versions` flag will +resolve the dependencies to the minimum SemVer version that will satisfy the +requirements (instead of the greatest version). + +The intended use-case of this flag is to check, during continuous integration, +that the versions specified in Cargo.toml are a correct reflection of the +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 +* Original Issue: [#4100](https://github.com/rust-lang/cargo/issues/4100) +* Tracking Issue: [#5657](https://github.com/rust-lang/cargo/issues/5657) + +When a `Cargo.lock` file is generated, the `-Z direct-minimal-versions` flag will +resolve the dependencies to the minimum SemVer version that will satisfy the +requirements (instead of the greatest version) for direct dependencies only. + +The intended use-case of this flag is to check, during continuous integration, +that the versions specified in Cargo.toml are a correct reflection of the +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`. + +Indirect dependencies are resolved as normal so as not to be blocked on their +minimal version validation. + +## artifact-dir +* Original Issue: [#4875](https://github.com/rust-lang/cargo/issues/4875) +* Tracking Issue: [#6790](https://github.com/rust-lang/cargo/issues/6790) + +This feature allows you to specify the directory where artifacts will be copied +to after they are built. Typically artifacts are only written to the +`target/release` or `target/debug` directories. However, determining the exact +filename can be tricky since you need to parse JSON output. The `--artifact-dir` +flag makes it easier to predictably access the artifacts. Note that the +artifacts are copied, so the originals are still in the `target` directory. +Example: + +```sh +cargo +nightly build --artifact-dir=out -Z unstable-options +``` + +This can also be specified in `.cargo/config.toml` files. + +```toml +[build] +artifact-dir = "out" +``` + +## root-dir +* Original Issue: [#9887](https://github.com/rust-lang/cargo/issues/9887) +* Tracking Issue: None (not currently slated for stabilization) + +The `-Zroot-dir` flag sets the root directory relative to which paths are printed. +This affects both diagnostics and paths emitted by the `file!()` macro. + +## 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) + +This flag changes `cargo test`'s behavior when handling doctests when +a target is passed. Currently, if a target is passed that is different +from the host cargo will simply skip testing doctests. If this flag is +present, cargo will continue as normal, passing the tests to doctest, +while also passing it a `--target` option, as well as enabling +`-Zunstable-features --enable-per-target-ignores` and passing along +information from `.cargo/config.toml`. See the rustc issue for more information. + +```sh +cargo test --target foo -Zdoctest-xcompile +``` + +## Build-plan +* Tracking Issue: [#5579](https://github.com/rust-lang/cargo/issues/5579) + +