Skip to content

Commit 4ac051e

Browse files
committed
Auto merge of #12975 - epage:git, r=weihanglo
fix(resolver): Don't do git fetches when updating workspace members ### What does this PR try to resolve? Before, when running `cargo update <member>`, we'd not reuse the previous resolve result and when the resolver started walking into the dependencies, it would do a git fetch. Now, we won't even try to resolve the workspace members and so we won't look at those dependencies and do git fetch. This will make `cargo update <workspace-member>` match `cargo update --workspace`. Fixes #12599 Fixes #8821 ### How should we test and review this PR? I considered whether there were other ways of handling this but I figured aiming for consistency in approaches was the best way. We can investigate improving those approaches separately. There are other discrepancies in the different code paths (handling of patches, adding sources) but I'm deferring looking over those. I added a test to demonstrate the `--workspace` behavior to use as a base line to compare with. ### Additional information Between this and #12602, this should finally resolve #12599.
2 parents 9765a44 + 9ca6376 commit 4ac051e

File tree

2 files changed

+108
-6
lines changed

2 files changed

+108
-6
lines changed

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,26 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
122122
}
123123
}
124124

125+
// Mirror `--workspace` and never avoid workspace members.
126+
// Filtering them out here so the above processes them normally
127+
// so their dependencies can be updated as requested
128+
to_avoid = to_avoid
129+
.into_iter()
130+
.filter(|id| {
131+
for package in ws.members() {
132+
let member_id = package.package_id();
133+
// Skip checking the `version` because `previous_resolve` might have a stale
134+
// value.
135+
// When dealing with workspace members, the other fields should be a
136+
// sufficiently unique match.
137+
if id.name() == member_id.name() && id.source_id() == member_id.source_id() {
138+
return false;
139+
}
140+
}
141+
true
142+
})
143+
.collect();
144+
125145
registry.add_sources(sources)?;
126146
}
127147

tests/testsuite/update.rs

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,11 +1091,8 @@ rustdns.workspace = true
10911091
p.cargo("update -p rootcrate")
10921092
.with_stderr(&format!(
10931093
"\
1094-
[UPDATING] git repository `{}`
10951094
[UPDATING] rootcrate v2.29.8 ([CWD]/rootcrate) -> v2.29.81
1096-
[UPDATING] rustdns v0.5.0 ([..]) -> [..]
10971095
[UPDATING] subcrate v2.29.8 ([CWD]/subcrate) -> v2.29.81",
1098-
git_project.url(),
10991096
))
11001097
.run();
11011098
}
@@ -1182,11 +1179,96 @@ rustdns.workspace = true
11821179
p.cargo("update -p crate2")
11831180
.with_stderr(&format!(
11841181
"\
1185-
[UPDATING] git repository `{}`
11861182
[UPDATING] crate1 v2.29.8 ([CWD]/crate1) -> v2.29.81
1187-
[UPDATING] crate2 v2.29.8 ([CWD]/crate2) -> v2.29.81
1188-
[UPDATING] rustdns v0.5.0 ([..]) -> [..]",
1183+
[UPDATING] crate2 v2.29.8 ([CWD]/crate2) -> v2.29.81",
1184+
))
1185+
.run();
1186+
}
1187+
1188+
#[cargo_test]
1189+
fn update_only_members_with_workspace() {
1190+
let git_project = git::new("rustdns", |project| {
1191+
project
1192+
.file("Cargo.toml", &basic_lib_manifest("rustdns"))
1193+
.file("src/lib.rs", "pub fn bar() {}")
1194+
});
1195+
1196+
let workspace_toml = format!(
1197+
r#"
1198+
[workspace.package]
1199+
version = "2.29.8"
1200+
edition = "2021"
1201+
publish = false
1202+
1203+
[workspace]
1204+
members = [
1205+
"crate2",
1206+
"crate1",
1207+
]
1208+
resolver = "2"
1209+
1210+
[workspace.dependencies]
1211+
# Internal crates
1212+
crate1 = {{ version = "*", path = "./crate1" }}
1213+
1214+
# External dependencies
1215+
rustdns = {{ version = "0.5.0", default-features = false, git = "{}" }}
1216+
"#,
1217+
git_project.url()
1218+
);
1219+
let p = project()
1220+
.file("Cargo.toml", &workspace_toml)
1221+
.file(
1222+
"crate2/Cargo.toml",
1223+
r#"
1224+
[package]
1225+
name = "crate2"
1226+
version.workspace = true
1227+
edition.workspace = true
1228+
publish.workspace = true
1229+
1230+
[dependencies]
1231+
crate1.workspace = true
1232+
"#,
1233+
)
1234+
.file("crate2/src/main.rs", "fn main() {}")
1235+
.file(
1236+
"crate1/Cargo.toml",
1237+
r#"
1238+
[package]
1239+
name = "crate1"
1240+
version.workspace = true
1241+
edition.workspace = true
1242+
publish.workspace = true
1243+
1244+
[dependencies]
1245+
rustdns.workspace = true
1246+
"#,
1247+
)
1248+
.file("crate1/src/lib.rs", "pub foo() {}")
1249+
.build();
1250+
1251+
// First time around we should compile both foo and bar
1252+
p.cargo("generate-lockfile")
1253+
.with_stderr(&format!(
1254+
"[UPDATING] git repository `{}`\n",
11891255
git_project.url(),
11901256
))
11911257
.run();
1258+
// Modify a file manually, shouldn't trigger a recompile
1259+
git_project.change_file("src/lib.rs", r#"pub fn bar() { println!("hello!"); }"#);
1260+
// Commit the changes and make sure we don't trigger a recompile because the
1261+
// lock file says not to change
1262+
let repo = git2::Repository::open(&git_project.root()).unwrap();
1263+
git::add(&repo);
1264+
git::commit(&repo);
1265+
p.change_file("Cargo.toml", &workspace_toml.replace("2.29.8", "2.29.81"));
1266+
1267+
p.cargo("update --workspace")
1268+
.with_stderr(
1269+
"\
1270+
[UPDATING] crate1 v2.29.8 ([CWD]/crate1) -> v2.29.81
1271+
[UPDATING] crate2 v2.29.8 ([CWD]/crate2) -> v2.29.81",
1272+
)
1273+
.run();
11921274
}

0 commit comments

Comments
 (0)