Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(vendor): Ensure sort happens for vendor #14004

Merged
merged 4 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2777,11 +2777,6 @@ fn prepare_targets_for_publish(
};
prepared.push(target);
}
// Ensure target order is deterministic, particularly for `cargo vendor` where re-vendoring
// shuld not cause changes.
//
// `unstable` should be deterministic because we enforce that `t.name` is unique
prepared.sort_unstable_by_key(|t| t.name.clone());

if prepared.is_empty() {
Ok(None)
Expand Down
10 changes: 8 additions & 2 deletions src/cargo/util/toml/targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ fn toml_targets_and_inferred(
autodiscover_flag_name: &str,
) -> Vec<TomlTarget> {
let inferred_targets = inferred_to_toml_targets(inferred);
match toml_targets {
let mut toml_targets = match toml_targets {
None => {
if let Some(false) = autodiscover {
vec![]
Expand Down Expand Up @@ -819,7 +819,13 @@ https://github.com/rust-lang/cargo/issues/5330",

targets
}
}
};
// Ensure target order is deterministic, particularly for `cargo vendor` where re-vendoring
// should not cause changes.
//
// `unstable` should be deterministic because we enforce that `t.name` is unique
toml_targets.sort_unstable_by_key(|t| t.name.clone());
toml_targets
}

fn inferred_to_toml_targets(inferred: &[(String, PathBuf)]) -> Vec<TomlTarget> {
Expand Down
127 changes: 125 additions & 2 deletions tests/testsuite/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3351,8 +3351,8 @@ See [..]
[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
[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
Expand Down Expand Up @@ -3384,8 +3384,8 @@ See [..]
[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
[WARNING] ignoring test `explicitpath` as `tests/explicitpath.rs` is not included in the published package
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
Expand Down Expand Up @@ -4928,3 +4928,126 @@ 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("")
.with_stderr(
"\
[PACKAGING] foo v0.0.1 ([CWD])
[VERIFYING] foo v0.0.1 ([CWD])
[COMPILING] foo v0.0.1 ([CWD][..])
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]
[PACKAGED] 10 files, [..] ([..] compressed)
",
)
.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",
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
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"
"#,
)],
);
}
2 changes: 1 addition & 1 deletion tests/testsuite/required_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1474,12 +1474,12 @@ fn truncated_install_warning_message() {
[FINISHED] `release` profile [optimized] target(s) in [..]
[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`
bin \"foo7\" 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();
}
127 changes: 127 additions & 0 deletions tests/testsuite/vendor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

use std::fs;

use cargo_test_support::compare::assert_e2e;
use cargo_test_support::git;
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]
Expand Down Expand Up @@ -862,6 +864,131 @@ fn git_complex() {
.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")
.exec_with_output()
.unwrap();
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.

bin = []
test = []
bench = []

[package]
edition = "2021"
name = "git_dep"
version = "0.0.1"
authors = []
build = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "foo"
documentation = "docs.rs/foo"
readme = false
license = "MIT"

[lib]
name = "git_dep"
path = [..]

[[example]]
name = "a"
path = [..]

[[example]]
name = "b"
path = [..]

[[example]]
name = "c"
path = [..]

[[example]]
name = "x"
path = [..]

[[example]]
name = "y"
path = [..]

[[example]]
name = "z"
path = [..]

"##]],
);
}

#[cargo_test]
fn depend_on_vendor_dir_not_deleted() {
let p = project()
Expand Down