@@ -6,6 +6,7 @@ use crate::core::global_cache_tracker;
66use crate :: core:: { Dependency , Package , PackageId } ;
77use crate :: sources:: IndexSummary ;
88use crate :: sources:: RecursivePathSource ;
9+ use crate :: sources:: git:: utils:: GitDatabase ;
910use crate :: sources:: git:: utils:: GitRemote ;
1011use crate :: sources:: git:: utils:: rev_to_oid;
1112use crate :: sources:: source:: MaybePackage ;
@@ -18,6 +19,7 @@ use crate::util::hex::short_hash;
1819use crate :: util:: interning:: InternedString ;
1920use anyhow:: Context as _;
2021use cargo_util:: paths:: exclude_from_backups_and_indexing;
22+ use git2:: Oid ;
2123use std:: fmt:: { self , Debug , Formatter } ;
2224use std:: task:: Poll ;
2325use tracing:: trace;
@@ -155,6 +157,63 @@ impl<'gctx> GitSource<'gctx> {
155157 } ) ;
156158 Ok ( ( ) )
157159 }
160+
161+ pub ( crate ) fn update_db ( & self ) -> CargoResult < ( GitDatabase , Oid ) > {
162+ let db_path = self . gctx . git_db_path ( ) . join ( & self . ident ) ;
163+ let db_path = db_path. into_path_unlocked ( ) ;
164+
165+ let db = self . remote . db_at ( & db_path) . ok ( ) ;
166+
167+ let ( db, actual_rev) = match ( & self . locked_rev , db) {
168+ // If we have a locked revision, and we have a preexisting database
169+ // which has that revision, then no update needs to happen.
170+ ( Revision :: Locked ( oid) , Some ( db) ) if db. contains ( * oid) => ( db, * oid) ,
171+
172+ // If we're in offline mode, we're not locked, and we have a
173+ // database, then try to resolve our reference with the preexisting
174+ // repository.
175+ ( Revision :: Deferred ( git_ref) , Some ( db) ) if !self . gctx . network_allowed ( ) => {
176+ let offline_flag = self
177+ . gctx
178+ . offline_flag ( )
179+ . expect ( "always present when `!network_allowed`" ) ;
180+ let rev = db. resolve ( & git_ref) . with_context ( || {
181+ format ! (
182+ "failed to lookup reference in preexisting repository, and \
183+ can't check for updates in offline mode ({offline_flag})"
184+ )
185+ } ) ?;
186+ ( db, rev)
187+ }
188+
189+ // ... otherwise we use this state to update the git database. Note
190+ // that we still check for being offline here, for example in the
191+ // situation that we have a locked revision but the database
192+ // doesn't have it.
193+ ( locked_rev, db) => {
194+ if let Some ( offline_flag) = self . gctx . offline_flag ( ) {
195+ anyhow:: bail!(
196+ "can't checkout from '{}': you are in the offline mode ({offline_flag})" ,
197+ self . remote. url( )
198+ ) ;
199+ }
200+
201+ if !self . quiet {
202+ self . gctx . shell ( ) . status (
203+ "Updating" ,
204+ format ! ( "git repository `{}`" , self . remote. url( ) ) ,
205+ ) ?;
206+ }
207+
208+ trace ! ( "updating git source `{:?}`" , self . remote) ;
209+
210+ let locked_rev = locked_rev. clone ( ) . into ( ) ;
211+ self . remote . checkout ( & db_path, db, & locked_rev, self . gctx ) ?
212+ }
213+ } ;
214+
215+ Ok ( ( db, actual_rev) )
216+ }
158217}
159218
160219/// Indicates a [Git revision] that might be locked or deferred to be resolved.
@@ -286,58 +345,7 @@ impl<'gctx> Source for GitSource<'gctx> {
286345 // exists.
287346 exclude_from_backups_and_indexing ( & git_path) ;
288347
289- let db_path = self . gctx . git_db_path ( ) . join ( & self . ident ) ;
290- let db_path = db_path. into_path_unlocked ( ) ;
291-
292- let db = self . remote . db_at ( & db_path) . ok ( ) ;
293-
294- let ( db, actual_rev) = match ( & self . locked_rev , db) {
295- // If we have a locked revision, and we have a preexisting database
296- // which has that revision, then no update needs to happen.
297- ( Revision :: Locked ( oid) , Some ( db) ) if db. contains ( * oid) => ( db, * oid) ,
298-
299- // If we're in offline mode, we're not locked, and we have a
300- // database, then try to resolve our reference with the preexisting
301- // repository.
302- ( Revision :: Deferred ( git_ref) , Some ( db) ) if !self . gctx . network_allowed ( ) => {
303- let offline_flag = self
304- . gctx
305- . offline_flag ( )
306- . expect ( "always present when `!network_allowed`" ) ;
307- let rev = db. resolve ( & git_ref) . with_context ( || {
308- format ! (
309- "failed to lookup reference in preexisting repository, and \
310- can't check for updates in offline mode ({offline_flag})"
311- )
312- } ) ?;
313- ( db, rev)
314- }
315-
316- // ... otherwise we use this state to update the git database. Note
317- // that we still check for being offline here, for example in the
318- // situation that we have a locked revision but the database
319- // doesn't have it.
320- ( locked_rev, db) => {
321- if let Some ( offline_flag) = self . gctx . offline_flag ( ) {
322- anyhow:: bail!(
323- "can't checkout from '{}': you are in the offline mode ({offline_flag})" ,
324- self . remote. url( )
325- ) ;
326- }
327-
328- if !self . quiet {
329- self . gctx . shell ( ) . status (
330- "Updating" ,
331- format ! ( "git repository `{}`" , self . remote. url( ) ) ,
332- ) ?;
333- }
334-
335- trace ! ( "updating git source `{:?}`" , self . remote) ;
336-
337- let locked_rev = locked_rev. clone ( ) . into ( ) ;
338- self . remote . checkout ( & db_path, db, & locked_rev, self . gctx ) ?
339- }
340- } ;
348+ let ( db, actual_rev) = self . update_db ( ) ?;
341349
342350 // Don’t use the full hash, in order to contribute less to reaching the
343351 // path length limit on Windows. See
0 commit comments