From 64a3ead1662bf38cca9029067f5eb5f40ed07850 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 6 Aug 2026 12:15:05 -0500 Subject: [PATCH 1/2] test(resolver): Show publish-time / min-publish-age interaction --- tests/testsuite/min_publish_age.rs | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/testsuite/min_publish_age.rs b/tests/testsuite/min_publish_age.rs index 23827d2f58d..20f4362a544 100644 --- a/tests/testsuite/min_publish_age.rs +++ b/tests/testsuite/min_publish_age.rs @@ -2051,3 +2051,64 @@ fn cargo_add_all_versions_too_new() { "#]]) .run(); } + +#[cargo_test] +fn generate_lockfile_with_publish_time_and_min_publish_age() { + publish_packages(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + + [dependencies] + bar = "1.0" + "#, + ) + .file( + ".cargo/config.toml", + r#" + [registry] + global-min-publish-age = "7 days" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo(&format!( + "generate-lockfile --publish-time {NOW} -Zmin-publish-age -Zunstable-options" + )) + .masquerade_as_nightly_cargo(&["publish-time", "min-publish-age"]) + .with_stderr_data(str![[r#" +[UPDATING] `dummy-registry` index +[LOCKING] 1 package to highest compatible version as of 2006-08-08T00:00:00Z + +"#]]) + .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 = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2216902cacb5611f65e00da63d917a6b9f4dbb10ddc39ee24c853322ab44b041" + +[[package]] +name = "foo" +version = "0.0.0" +dependencies = [ + "bar", +] + +"##]], + ); +} From 9eae326643be54677ec53367f11162cffc346627 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 6 Aug 2026 12:22:55 -0500 Subject: [PATCH 2/2] fix(resolver): Make min-publish-age relative to --publish-time This is to simplify the workflow for the time traveling aspect of `--publish-time`. You can go into a repo and set a time and get the results as if it is that time. You don't need to look up the min-publish-age and do the math manually. If there are multiple registries, that becomes even more difficult. Granted, this is of limited use while it is a flag on `cargo generate-lockfile`. I could see moving this to `resolver.now` or something. --- src/ops/cargo_add/mod.rs | 2 +- src/ops/cargo_update.rs | 4 +++- src/ops/resolve.rs | 2 +- src/resolver/version_prefs.rs | 11 +++++++---- tests/testsuite/min_publish_age.rs | 5 +++-- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ops/cargo_add/mod.rs b/src/ops/cargo_add/mod.rs index ae514c22d88..05b6a8de126 100644 --- a/src/ops/cargo_add/mod.rs +++ b/src/ops/cargo_add/mod.rs @@ -849,7 +849,7 @@ fn get_latest_dependency( // `cargo add` selects a version outside the resolver, // so the `min-publish-age` policy must be applied here too. - let publish_age = PublishAgePolicy::new(gctx)?; + let publish_age = PublishAgePolicy::new(None, gctx)?; if let Some(publish_age) = &publish_age { let mut too_new = Vec::new(); possibilities.retain(|s| match publish_age.too_new(s) { diff --git a/src/ops/cargo_update.rs b/src/ops/cargo_update.rs index 272b2f83b6f..7b96cb25424 100644 --- a/src/ops/cargo_update.rs +++ b/src/ops/cargo_update.rs @@ -806,7 +806,9 @@ fn publish_age_policy_for_report(ws: &Workspace<'_>) -> Option if !ws.resolve_honors_publish_age() { return None; } - PublishAgePolicy::for_report(ws.gctx()).ok().flatten() + PublishAgePolicy::for_report(ws.resolve_publish_time(), ws.gctx()) + .ok() + .flatten() } fn report_required_rust_version(resolve: &Resolve, change: &PackageChange) -> Option { diff --git a/src/ops/resolve.rs b/src/ops/resolve.rs index 0702aa71d93..bcb905ff01a 100644 --- a/src/ops/resolve.rs +++ b/src/ops/resolve.rs @@ -473,7 +473,7 @@ pub fn resolve_with_previous<'gctx>( version_prefs.publish_time(publish_time); } if ws.resolve_honors_publish_age() { - if let Some(policy) = PublishAgePolicy::new(ws.gctx())? { + if let Some(policy) = PublishAgePolicy::new(ws.resolve_publish_time(), ws.gctx())? { version_prefs.publish_age(policy); } } diff --git a/src/resolver/version_prefs.rs b/src/resolver/version_prefs.rs index 947df5b0290..0e3edd5ee80 100644 --- a/src/resolver/version_prefs.rs +++ b/src/resolver/version_prefs.rs @@ -176,7 +176,7 @@ impl PublishAgePolicy { /// * the `-Zmin-publish-age` gate is off /// * the resolver is configured to allow pubtime-incompatible versions /// * no threshold is configured at all - pub fn new(gctx: &GlobalContext) -> CargoResult> { + pub fn new(now: Option, gctx: &GlobalContext) -> CargoResult> { let resolver_config = gctx.get::>("resolver")?; if resolver_config .and_then(|c| c.incompatible_publish_age) @@ -185,12 +185,15 @@ impl PublishAgePolicy { return Ok(None); } - Self::for_report(gctx) + Self::for_report(now, gctx) } /// Like [`PublishAgePolicy::new`] but ignore config from `[resolver]`, /// so it report too-new packages regardess they are allowed or denied. - pub fn for_report(gctx: &GlobalContext) -> CargoResult> { + pub fn for_report( + now: Option, + gctx: &GlobalContext, + ) -> CargoResult> { if !gctx.cli_unstable().min_publish_age { return Ok(None); } @@ -239,7 +242,7 @@ impl PublishAgePolicy { } Ok(Some(Self { - invocation_time: gctx.invocation_time(), + invocation_time: now.unwrap_or_else(|| gctx.invocation_time()), global, crates_io, per_registry, diff --git a/tests/testsuite/min_publish_age.rs b/tests/testsuite/min_publish_age.rs index 20f4362a544..69460d62fad 100644 --- a/tests/testsuite/min_publish_age.rs +++ b/tests/testsuite/min_publish_age.rs @@ -2084,6 +2084,7 @@ fn generate_lockfile_with_publish_time_and_min_publish_age() { .with_stderr_data(str![[r#" [UPDATING] `dummy-registry` index [LOCKING] 1 package to highest compatible version as of 2006-08-08T00:00:00Z +[ADDING] bar v1.0.0 (available: v1.1.0, published 2 days ago) "#]]) .run(); @@ -2098,9 +2099,9 @@ version = 4 [[package]] name = "bar" -version = "1.1.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2216902cacb5611f65e00da63d917a6b9f4dbb10ddc39ee24c853322ab44b041" +checksum = "75120345f1869de1197d82823818e8151ad3325d58f084044181fc4457c087c4" [[package]] name = "foo"