diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index c81c5ba995d..90c38fab952 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -155,6 +155,20 @@ impl<'gctx> GitSource<'gctx> { }); Ok(()) } + + /// Whether the registry is up-to-date. See [`Self::mark_updated`] for more. + fn is_updated(&self) -> bool { + self.gctx.updated_sources().contains(&self.source_id) + } + + /// Marks this registry as up-to-date. + /// + /// This makes sure the index is only updated once per session since it is + /// an expensive operation. This generally only happens when the resolver + /// is run multiple times, such as during `cargo publish`. + fn mark_updated(&self) { + self.gctx.updated_sources().insert(self.source_id); + } } /// Indicates a [Git revision] that might be locked or deferred to be resolved. @@ -296,6 +310,14 @@ impl<'gctx> Source for GitSource<'gctx> { // which has that revision, then no update needs to happen. (Revision::Locked(oid), Some(db)) if db.contains(*oid) => (db, *oid), + // If we've already checked out this source, try resolving the reference. + (Revision::Deferred(git_ref), Some(db)) if self.is_updated() => { + let rev = db.resolve(&git_ref).with_context(|| { + format!("failed to lookup reference in preexisting repository") + })?; + (db, rev) + } + // If we're in offline mode, we're not locked, and we have a // database, then try to resolve our reference with the preexisting // repository. @@ -318,6 +340,7 @@ impl<'gctx> Source for GitSource<'gctx> { // situation that we have a locked revision but the database // doesn't have it. (locked_rev, db) => { + self.mark_updated(); if let Some(offline_flag) = self.gctx.offline_flag() { anyhow::bail!( "can't checkout from '{}': you are in the offline mode ({offline_flag})", diff --git a/src/cargo/sources/registry/http_remote.rs b/src/cargo/sources/registry/http_remote.rs index 9464d36a5bd..8cef512b0c3 100644 --- a/src/cargo/sources/registry/http_remote.rs +++ b/src/cargo/sources/registry/http_remote.rs @@ -252,6 +252,20 @@ impl<'gctx> HttpRegistry<'gctx> { Some((tag, value)) } + /// Whether the registry is up-to-date. See [`Self::mark_updated`] for more. + fn is_updated(&self) -> bool { + self.gctx.updated_sources().contains(&self.source_id) + } + + /// Marks this registry as up-to-date. + /// + /// This makes sure the index is only updated once per session since it is + /// an expensive operation. This generally only happens when the resolver + /// is run multiple times, such as during `cargo publish`. + fn mark_updated(&self) { + self.gctx.updated_sources().insert(self.source_id); + } + /// Setup the necessary works before the first fetch gets started. /// /// This is a no-op if called more than one time. @@ -262,6 +276,11 @@ impl<'gctx> HttpRegistry<'gctx> { } self.fetch_started = true; + if self.is_updated() { + return Ok(()); + } + self.mark_updated(); + // We've enabled the `http2` feature of `curl` in Cargo, so treat // failures here as fatal as it would indicate a build-time problem. self.multiplexing = self.gctx.http_config()?.multiplexing.unwrap_or(true);