Skip to content

Commit 7034e2a

Browse files
committed
Auto merge of #14004 - epage:deterministic, r=weihanglo
fix(vendor): Ensure sort happens for vendor ### What does this PR try to resolve? This is a follow up to #13989 which sorted in time for `cargo package` and `cargo publish` but too late for `cargo vendor`. This moves the sorting earlier and puts it in a place that will only run when resolving. Fixes #13988 ### How should we test and review this PR? I had assumed tests existed but just happened to write in a way that leads to sorting. Apparently not. I've added some tests. The `cargo vendor` test has to elide paths because `/`s are normalized during publish, rather than resolve, so the output varies across platforms, even with cargo-test-support normalizing slashes because `toml` will switch between `"` and `'`. ### Additional information
2 parents 8114c9a + 150461c commit 7034e2a

File tree

5 files changed

+261
-10
lines changed

5 files changed

+261
-10
lines changed

src/cargo/util/toml/mod.rs

-5
Original file line numberDiff line numberDiff line change
@@ -2777,11 +2777,6 @@ fn prepare_targets_for_publish(
27772777
};
27782778
prepared.push(target);
27792779
}
2780-
// Ensure target order is deterministic, particularly for `cargo vendor` where re-vendoring
2781-
// shuld not cause changes.
2782-
//
2783-
// `unstable` should be deterministic because we enforce that `t.name` is unique
2784-
prepared.sort_unstable_by_key(|t| t.name.clone());
27852780

27862781
if prepared.is_empty() {
27872782
Ok(None)

src/cargo/util/toml/targets.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ fn toml_targets_and_inferred(
744744
autodiscover_flag_name: &str,
745745
) -> Vec<TomlTarget> {
746746
let inferred_targets = inferred_to_toml_targets(inferred);
747-
match toml_targets {
747+
let mut toml_targets = match toml_targets {
748748
None => {
749749
if let Some(false) = autodiscover {
750750
vec![]
@@ -819,7 +819,13 @@ https://github.com/rust-lang/cargo/issues/5330",
819819

820820
targets
821821
}
822-
}
822+
};
823+
// Ensure target order is deterministic, particularly for `cargo vendor` where re-vendoring
824+
// should not cause changes.
825+
//
826+
// `unstable` should be deterministic because we enforce that `t.name` is unique
827+
toml_targets.sort_unstable_by_key(|t| t.name.clone());
828+
toml_targets
823829
}
824830

825831
fn inferred_to_toml_targets(inferred: &[(String, PathBuf)]) -> Vec<TomlTarget> {

tests/testsuite/package.rs

+125-2
Original file line numberDiff line numberDiff line change
@@ -3351,8 +3351,8 @@ See [..]
33513351
[WARNING] ignoring `package.build` as `build.rs` is not included in the published package
33523352
[WARNING] ignoring binary `foo` as `src/main.rs` is not included in the published package
33533353
[WARNING] ignoring example `ExampleFoo` as `examples/ExampleFoo.rs` is not included in the published package
3354-
[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package
33553354
[WARNING] ignoring test `ExplicitPath` as `tests/ExplicitPath.rs` is not included in the published package
3355+
[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package
33563356
[VERIFYING] foo v0.0.1 ([CWD])
33573357
[COMPILING] foo v0.0.1 ([CWD][..])
33583358
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
@@ -3384,8 +3384,8 @@ See [..]
33843384
[WARNING] ignoring `package.build` as `build.rs` is not included in the published package
33853385
[WARNING] ignoring binary `foo` as `src/main.rs` is not included in the published package
33863386
[WARNING] ignoring example `ExampleFoo` as `examples/ExampleFoo.rs` is not included in the published package
3387-
[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package
33883387
[WARNING] ignoring test `ExplicitPath` as `tests/ExplicitPath.rs` is not included in the published package
3388+
[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package
33893389
[VERIFYING] foo v0.0.1 ([CWD])
33903390
[COMPILING] foo v0.0.1 ([CWD][..])
33913391
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
@@ -4928,3 +4928,126 @@ path = "src/lib.rs"
49284928
)],
49294929
);
49304930
}
4931+
4932+
#[cargo_test]
4933+
fn deterministic_build_targets() {
4934+
let p = project()
4935+
.file(
4936+
"Cargo.toml",
4937+
r#"
4938+
[package]
4939+
name = "foo"
4940+
version = "0.0.1"
4941+
edition = "2021"
4942+
license = "MIT"
4943+
description = "foo"
4944+
documentation = "docs.rs/foo"
4945+
authors = []
4946+
4947+
[[example]]
4948+
name = "c"
4949+
4950+
[[example]]
4951+
name = "b"
4952+
4953+
[[example]]
4954+
name = "a"
4955+
"#,
4956+
)
4957+
.file("src/lib.rs", "")
4958+
.file("examples/z.rs", "fn main() {}")
4959+
.file("examples/y.rs", "fn main() {}")
4960+
.file("examples/x.rs", "fn main() {}")
4961+
.file("examples/c.rs", "fn main() {}")
4962+
.file("examples/b.rs", "fn main() {}")
4963+
.file("examples/a.rs", "fn main() {}")
4964+
.build();
4965+
4966+
p.cargo("package")
4967+
.with_stdout("")
4968+
.with_stderr(
4969+
"\
4970+
[PACKAGING] foo v0.0.1 ([CWD])
4971+
[VERIFYING] foo v0.0.1 ([CWD])
4972+
[COMPILING] foo v0.0.1 ([CWD][..])
4973+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
4974+
[PACKAGED] 10 files, [..] ([..] compressed)
4975+
",
4976+
)
4977+
.run();
4978+
4979+
let f = File::open(&p.root().join("target/package/foo-0.0.1.crate")).unwrap();
4980+
validate_crate_contents(
4981+
f,
4982+
"foo-0.0.1.crate",
4983+
&[
4984+
"Cargo.lock",
4985+
"Cargo.toml",
4986+
"Cargo.toml.orig",
4987+
"src/lib.rs",
4988+
"examples/a.rs",
4989+
"examples/b.rs",
4990+
"examples/c.rs",
4991+
"examples/x.rs",
4992+
"examples/y.rs",
4993+
"examples/z.rs",
4994+
],
4995+
&[(
4996+
"Cargo.toml",
4997+
r#"# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
4998+
#
4999+
# When uploading crates to the registry Cargo will automatically
5000+
# "normalize" Cargo.toml files for maximal compatibility
5001+
# with all versions of Cargo and also rewrite `path` dependencies
5002+
# to registry (e.g., crates.io) dependencies.
5003+
#
5004+
# If you are reading this file be aware that the original Cargo.toml
5005+
# will likely look very different (and much more reasonable).
5006+
# See Cargo.toml.orig for the original contents.
5007+
5008+
[package]
5009+
edition = "2021"
5010+
name = "foo"
5011+
version = "0.0.1"
5012+
authors = []
5013+
build = false
5014+
autobins = false
5015+
autoexamples = false
5016+
autotests = false
5017+
autobenches = false
5018+
description = "foo"
5019+
documentation = "docs.rs/foo"
5020+
readme = false
5021+
license = "MIT"
5022+
5023+
[lib]
5024+
name = "foo"
5025+
path = "src/lib.rs"
5026+
5027+
[[example]]
5028+
name = "a"
5029+
path = "examples/a.rs"
5030+
5031+
[[example]]
5032+
name = "b"
5033+
path = "examples/b.rs"
5034+
5035+
[[example]]
5036+
name = "c"
5037+
path = "examples/c.rs"
5038+
5039+
[[example]]
5040+
name = "x"
5041+
path = "examples/x.rs"
5042+
5043+
[[example]]
5044+
name = "y"
5045+
path = "examples/y.rs"
5046+
5047+
[[example]]
5048+
name = "z"
5049+
path = "examples/z.rs"
5050+
"#,
5051+
)],
5052+
);
5053+
}

tests/testsuite/required_features.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1474,12 +1474,12 @@ fn truncated_install_warning_message() {
14741474
[FINISHED] `release` profile [optimized] target(s) in [..]
14751475
[WARNING] none of the package's binaries are available for install using the selected features
14761476
bin \"foo1\" requires the features: `feature1`, `feature2`, `feature3`
1477+
bin \"foo10\" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5`
14771478
bin \"foo2\" requires the features: `feature2`
14781479
bin \"foo3\" requires the features: `feature3`
14791480
bin \"foo4\" requires the features: `feature4`, `feature1`
14801481
bin \"foo5\" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5`
14811482
bin \"foo6\" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5`
1482-
bin \"foo7\" requires the features: `feature1`, `feature2`, `feature3`, `feature4`, `feature5`
14831483
4 more targets also requires features not enabled. See them in the Cargo.toml file.
14841484
Consider enabling some of the needed features by passing, e.g., `--features=\"feature1 feature2 feature3\"`").run();
14851485
}

tests/testsuite/vendor.rs

+127
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
77
use std::fs;
88

9+
use cargo_test_support::compare::assert_e2e;
910
use cargo_test_support::git;
1011
use cargo_test_support::registry::{self, Package, RegistryBuilder};
12+
use cargo_test_support::str;
1113
use cargo_test_support::{basic_lib_manifest, basic_manifest, paths, project, Project};
1214

1315
#[cargo_test]
@@ -862,6 +864,131 @@ fn git_complex() {
862864
.run();
863865
}
864866

867+
#[cargo_test]
868+
fn git_deterministic() {
869+
let git_dep = git::new("git_dep", |p| {
870+
p.file(
871+
"Cargo.toml",
872+
r#"
873+
[package]
874+
name = "git_dep"
875+
version = "0.0.1"
876+
edition = "2021"
877+
license = "MIT"
878+
description = "foo"
879+
documentation = "docs.rs/foo"
880+
authors = []
881+
882+
[[example]]
883+
name = "c"
884+
885+
[[example]]
886+
name = "b"
887+
888+
[[example]]
889+
name = "a"
890+
"#,
891+
)
892+
.file("src/lib.rs", "")
893+
.file("examples/z.rs", "fn main() {}")
894+
.file("examples/y.rs", "fn main() {}")
895+
.file("examples/x.rs", "fn main() {}")
896+
.file("examples/c.rs", "fn main() {}")
897+
.file("examples/b.rs", "fn main() {}")
898+
.file("examples/a.rs", "fn main() {}")
899+
});
900+
901+
let p = project()
902+
.file(
903+
"Cargo.toml",
904+
&format!(
905+
r#"
906+
[package]
907+
name = "foo"
908+
version = "0.1.0"
909+
910+
[dependencies]
911+
git_dep = {{ git = '{}' }}
912+
"#,
913+
git_dep.url()
914+
),
915+
)
916+
.file("src/lib.rs", "")
917+
.build();
918+
919+
let output = p
920+
.cargo("vendor --respect-source-config")
921+
.exec_with_output()
922+
.unwrap();
923+
let output = String::from_utf8(output.stdout).unwrap();
924+
p.change_file(".cargo/config.toml", &output);
925+
926+
let git_dep_manifest = p.read_file("vendor/git_dep/Cargo.toml");
927+
assert_e2e().eq(
928+
git_dep_manifest,
929+
str![[r##"
930+
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
931+
#
932+
# When uploading crates to the registry Cargo will automatically
933+
# "normalize" Cargo.toml files for maximal compatibility
934+
# with all versions of Cargo and also rewrite `path` dependencies
935+
# to registry (e.g., crates.io) dependencies.
936+
#
937+
# If you are reading this file be aware that the original Cargo.toml
938+
# will likely look very different (and much more reasonable).
939+
# See Cargo.toml.orig for the original contents.
940+
941+
bin = []
942+
test = []
943+
bench = []
944+
945+
[package]
946+
edition = "2021"
947+
name = "git_dep"
948+
version = "0.0.1"
949+
authors = []
950+
build = false
951+
autobins = false
952+
autoexamples = false
953+
autotests = false
954+
autobenches = false
955+
description = "foo"
956+
documentation = "docs.rs/foo"
957+
readme = false
958+
license = "MIT"
959+
960+
[lib]
961+
name = "git_dep"
962+
path = [..]
963+
964+
[[example]]
965+
name = "a"
966+
path = [..]
967+
968+
[[example]]
969+
name = "b"
970+
path = [..]
971+
972+
[[example]]
973+
name = "c"
974+
path = [..]
975+
976+
[[example]]
977+
name = "x"
978+
path = [..]
979+
980+
[[example]]
981+
name = "y"
982+
path = [..]
983+
984+
[[example]]
985+
name = "z"
986+
path = [..]
987+
988+
"##]],
989+
);
990+
}
991+
865992
#[cargo_test]
866993
fn depend_on_vendor_dir_not_deleted() {
867994
let p = project()

0 commit comments

Comments
 (0)