Skip to content

Commit 2607661

Browse files
committed
Auto merge of #14049 - tweag:issue-12425-more-tests, r=epage
More `update --breaking` tests Related to #12425 (comment) in #12425.
2 parents c81c32b + f41bdc1 commit 2607661

File tree

3 files changed

+633
-59
lines changed

3 files changed

+633
-59
lines changed

src/cargo/ops/cargo_update.rs

+67-47
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ pub fn upgrade_manifests(
222222
let mut upgrades = HashMap::new();
223223
let mut upgrade_messages = HashSet::new();
224224

225+
let to_update = to_update
226+
.iter()
227+
.map(|s| PackageIdSpec::parse(s))
228+
.collect::<Result<Vec<_>, _>>()?;
229+
225230
// Updates often require a lot of modifications to the registry, so ensure
226231
// that we're synchronized against other Cargos.
227232
let _lock = gctx.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
@@ -239,7 +244,7 @@ pub fn upgrade_manifests(
239244
.try_map_dependencies(|d| {
240245
upgrade_dependency(
241246
&gctx,
242-
to_update,
247+
&to_update,
243248
&mut registry,
244249
&mut upgrades,
245250
&mut upgrade_messages,
@@ -253,7 +258,7 @@ pub fn upgrade_manifests(
253258

254259
fn upgrade_dependency(
255260
gctx: &GlobalContext,
256-
to_update: &Vec<String>,
261+
to_update: &Vec<PackageIdSpec>,
257262
registry: &mut PackageRegistry<'_>,
258263
upgrades: &mut UpgradeMap,
259264
upgrade_messages: &mut HashSet<String>,
@@ -263,46 +268,48 @@ fn upgrade_dependency(
263268
let renamed_to = dependency.name_in_toml();
264269

265270
if name != renamed_to {
266-
trace!(
267-
"skipping dependency renamed from `{}` to `{}`",
268-
name,
269-
renamed_to
270-
);
271+
trace!("skipping dependency renamed from `{name}` to `{renamed_to}`");
271272
return Ok(dependency);
272273
}
273274

274-
if !to_update.is_empty() && !to_update.contains(&name.to_string()) {
275-
trace!("skipping dependency `{}` not selected for upgrading", name);
275+
if !to_update.is_empty()
276+
&& !to_update.iter().any(|spec| {
277+
spec.name() == name.as_str()
278+
&& dependency.source_id().is_registry()
279+
&& spec
280+
.url()
281+
.map_or(true, |url| url == dependency.source_id().url())
282+
&& spec
283+
.version()
284+
.map_or(true, |v| dependency.version_req().matches(&v))
285+
})
286+
{
287+
trace!("skipping dependency `{name}` not selected for upgrading");
276288
return Ok(dependency);
277289
}
278290

279291
if !dependency.source_id().is_registry() {
280-
trace!("skipping non-registry dependency: {}", name);
292+
trace!("skipping non-registry dependency: {name}");
281293
return Ok(dependency);
282294
}
283295

284296
let version_req = dependency.version_req();
285297

286298
let OptVersionReq::Req(current) = version_req else {
287-
trace!(
288-
"skipping dependency `{}` without a simple version requirement: {}",
289-
name,
290-
version_req
291-
);
299+
trace!("skipping dependency `{name}` without a simple version requirement: {version_req}");
292300
return Ok(dependency);
293301
};
294302

295303
let [comparator] = &current.comparators[..] else {
296304
trace!(
297-
"skipping dependency `{}` with multiple version comparators: {:?}",
298-
name,
305+
"skipping dependency `{name}` with multiple version comparators: {:?}",
299306
&current.comparators
300307
);
301308
return Ok(dependency);
302309
};
303310

304311
if comparator.op != Op::Caret {
305-
trace!("skipping non-caret dependency `{}`: {}", name, comparator);
312+
trace!("skipping non-caret dependency `{name}`: {comparator}");
306313
return Ok(dependency);
307314
}
308315

@@ -332,30 +339,21 @@ fn upgrade_dependency(
332339
};
333340

334341
let Some(latest) = latest else {
335-
trace!(
336-
"skipping dependency `{}` without any published versions",
337-
name
338-
);
342+
trace!("skipping dependency `{name}` without any published versions");
339343
return Ok(dependency);
340344
};
341345

342346
if current.matches(&latest) {
343-
trace!(
344-
"skipping dependency `{}` without a breaking update available",
345-
name
346-
);
347+
trace!("skipping dependency `{name}` without a breaking update available");
347348
return Ok(dependency);
348349
}
349350

350-
let Some(new_req_string) = upgrade_requirement(&current.to_string(), latest)? else {
351-
trace!(
352-
"skipping dependency `{}` because the version requirement didn't change",
353-
name
354-
);
351+
let Some((new_req_string, _)) = upgrade_requirement(&current.to_string(), latest)? else {
352+
trace!("skipping dependency `{name}` because the version requirement didn't change");
355353
return Ok(dependency);
356354
};
357355

358-
let upgrade_message = format!("{} {} -> {}", name, current, new_req_string);
356+
let upgrade_message = format!("{name} {current} -> {new_req_string}");
359357
trace!(upgrade_message);
360358

361359
if upgrade_messages.insert(upgrade_message.clone()) {
@@ -371,8 +369,17 @@ fn upgrade_dependency(
371369
Ok(dep)
372370
}
373371

374-
/// Update manifests with upgraded versions, and write to disk. Based on cargo-edit.
375-
/// Returns true if any file has changed.
372+
/// Update manifests with upgraded versions, and write to disk. Based on
373+
/// cargo-edit. Returns true if any file has changed.
374+
///
375+
/// Some of the checks here are duplicating checks already done in
376+
/// upgrade_manifests/upgrade_dependency. Why? Let's say upgrade_dependency has
377+
/// found that dependency foo was eligible for an upgrade. But foo can occur in
378+
/// multiple manifest files, and even multiple times in the same manifest file,
379+
/// and may be pinned, renamed, etc. in some of the instances. So we still need
380+
/// to check here which dependencies to actually modify. So why not drop the
381+
/// upgrade map and redo all checks here? Because then we'd have to query the
382+
/// registries again to find the latest versions.
376383
pub fn write_manifest_upgrades(
377384
ws: &Workspace<'_>,
378385
upgrades: &UpgradeMap,
@@ -389,10 +396,7 @@ pub fn write_manifest_upgrades(
389396
.collect::<Vec<_>>();
390397

391398
for manifest_path in manifest_paths {
392-
trace!(
393-
"updating TOML manifest at `{:?}` with upgraded dependencies",
394-
manifest_path
395-
);
399+
trace!("updating TOML manifest at `{manifest_path:?}` with upgraded dependencies");
396400

397401
let crate_root = manifest_path
398402
.parent()
@@ -410,41 +414,57 @@ pub fn write_manifest_upgrades(
410414
dep_key_str,
411415
dep_item,
412416
)?;
417+
let name = &dependency.name;
418+
419+
if let Some(renamed_to) = dependency.rename {
420+
trace!("skipping dependency renamed from `{name}` to `{renamed_to}`");
421+
continue;
422+
}
413423

414424
let Some(current) = dependency.version() else {
415-
trace!("skipping dependency without a version: {}", dependency.name);
425+
trace!("skipping dependency without a version: {name}");
416426
continue;
417427
};
418428

419429
let (MaybeWorkspace::Other(source_id), Some(Source::Registry(source))) =
420430
(dependency.source_id(ws.gctx())?, dependency.source())
421431
else {
422-
trace!("skipping non-registry dependency: {}", dependency.name);
432+
trace!("skipping non-registry dependency: {name}");
423433
continue;
424434
};
425435

426-
let Some(latest) = upgrades.get(&(dependency.name.to_owned(), source_id)) else {
436+
let Some(latest) = upgrades.get(&(name.to_owned(), source_id)) else {
437+
trace!("skipping dependency without an upgrade: {name}");
438+
continue;
439+
};
440+
441+
let Some((new_req_string, new_req)) = upgrade_requirement(current, latest)? else {
427442
trace!(
428-
"skipping dependency without an upgrade: {}",
429-
dependency.name
443+
"skipping dependency `{name}` because the version requirement didn't change"
430444
);
431445
continue;
432446
};
433447

434-
let Some(new_req_string) = upgrade_requirement(current, latest)? else {
448+
let [comparator] = &new_req.comparators[..] else {
435449
trace!(
436-
"skipping dependency `{}` because the version requirement didn't change",
437-
dependency.name
450+
"skipping dependency `{}` with multiple version comparators: {:?}",
451+
name,
452+
new_req.comparators
438453
);
439454
continue;
440455
};
441456

457+
if comparator.op != Op::Caret {
458+
trace!("skipping non-caret dependency `{}`: {}", name, comparator);
459+
continue;
460+
}
461+
442462
let mut dep = dependency.clone();
443463
let mut source = source.clone();
444464
source.version = new_req_string;
445465
dep.source = Some(Source::Registry(source));
446466

447-
trace!("upgrading dependency {}", dependency.name);
467+
trace!("upgrading dependency {name}");
448468
dep.update_toml(&crate_root, &mut dep_key, dep_item);
449469
manifest_has_changed = true;
450470
any_file_has_changed = true;

src/cargo/util/toml_mut/upgrade.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::CargoResult;
77
pub(crate) fn upgrade_requirement(
88
req: &str,
99
version: &semver::Version,
10-
) -> CargoResult<Option<String>> {
10+
) -> CargoResult<Option<(String, semver::VersionReq)>> {
1111
let req_text = req.to_string();
1212
let raw_req = semver::VersionReq::parse(&req_text)
1313
.expect("semver to generate valid version requirements");
@@ -40,7 +40,7 @@ pub(crate) fn upgrade_requirement(
4040
if new_req_text == req_text {
4141
Ok(None)
4242
} else {
43-
Ok(Some(new_req_text))
43+
Ok(Some((new_req_text, new_req)))
4444
}
4545
}
4646
}
@@ -103,7 +103,9 @@ mod test {
103103
#[track_caller]
104104
fn assert_req_bump<'a, O: Into<Option<&'a str>>>(version: &str, req: &str, expected: O) {
105105
let version = semver::Version::parse(version).unwrap();
106-
let actual = upgrade_requirement(req, &version).unwrap();
106+
let actual = upgrade_requirement(req, &version)
107+
.unwrap()
108+
.map(|(actual, _req)| actual);
107109
let expected = expected.into();
108110
assert_eq!(actual.as_deref(), expected);
109111
}

0 commit comments

Comments
 (0)