@@ -181,9 +181,14 @@ impl GitDatabase {
181
181
. filter ( |co| co. is_fresh ( ) )
182
182
{
183
183
Some ( co) => co,
184
- None => GitCheckout :: clone_into ( dest, self , rev, gctx) ?,
184
+ None => {
185
+ let ( checkout, guard) = GitCheckout :: clone_into ( dest, self , rev, gctx) ?;
186
+ checkout. update_submodules ( gctx) ?;
187
+ guard. mark_ok ( ) ?;
188
+ checkout
189
+ }
185
190
} ;
186
- checkout . update_submodules ( gctx ) ? ;
191
+
187
192
Ok ( checkout)
188
193
}
189
194
@@ -280,7 +285,7 @@ impl<'a> GitCheckout<'a> {
280
285
database : & ' a GitDatabase ,
281
286
revision : git2:: Oid ,
282
287
gctx : & GlobalContext ,
283
- ) -> CargoResult < GitCheckout < ' a > > {
288
+ ) -> CargoResult < ( GitCheckout < ' a > , CheckoutGuard ) > {
284
289
let dirname = into. parent ( ) . unwrap ( ) ;
285
290
paths:: create_dir_all ( & dirname) ?;
286
291
if into. exists ( ) {
@@ -329,8 +334,8 @@ impl<'a> GitCheckout<'a> {
329
334
let repo = repo. unwrap ( ) ;
330
335
331
336
let checkout = GitCheckout :: new ( database, revision, repo) ;
332
- checkout. reset ( gctx) ?;
333
- Ok ( checkout)
337
+ let guard = checkout. reset ( gctx) ?;
338
+ Ok ( ( checkout, guard ) )
334
339
}
335
340
336
341
/// Checks if the `HEAD` of this checkout points to the expected revision.
@@ -355,12 +360,12 @@ impl<'a> GitCheckout<'a> {
355
360
/// To enable this we have a dummy file in our checkout, [`.cargo-ok`],
356
361
/// which if present means that the repo has been successfully reset and is
357
362
/// ready to go. Hence if we start to do a reset, we make sure this file
358
- /// *doesn't* exist, and then once we're done we create the file.
363
+ /// *doesn't* exist. The caller of [`reset`] has an option to perform additional operations
364
+ /// (e.g. submodule update) before marking the check-out as ready.
359
365
///
360
366
/// [`.cargo-ok`]: CHECKOUT_READY_LOCK
361
- fn reset ( & self , gctx : & GlobalContext ) -> CargoResult < ( ) > {
362
- let ok_file = self . path . join ( CHECKOUT_READY_LOCK ) ;
363
- let _ = paths:: remove_file ( & ok_file) ;
367
+ fn reset ( & self , gctx : & GlobalContext ) -> CargoResult < CheckoutGuard > {
368
+ let guard = CheckoutGuard :: guard ( & self . path ) ;
364
369
info ! ( "reset {} to {}" , self . repo. path( ) . display( ) , self . revision) ;
365
370
366
371
// Ensure libgit2 won't mess with newlines when we vendor.
@@ -370,8 +375,8 @@ impl<'a> GitCheckout<'a> {
370
375
371
376
let object = self . repo . find_object ( self . revision , None ) ?;
372
377
reset ( & self . repo , & object, gctx) ?;
373
- paths :: create ( ok_file ) ? ;
374
- Ok ( ( ) )
378
+
379
+ Ok ( guard )
375
380
}
376
381
377
382
/// Like `git submodule update --recursive` but for this git checkout.
@@ -479,6 +484,25 @@ impl<'a> GitCheckout<'a> {
479
484
}
480
485
}
481
486
487
+ /// See [`GitCheckout::reset`] for rationale on this type.
488
+ #[ must_use]
489
+ struct CheckoutGuard {
490
+ ok_file : PathBuf ,
491
+ }
492
+
493
+ impl CheckoutGuard {
494
+ fn guard ( path : & Path ) -> Self {
495
+ let ok_file = path. join ( CHECKOUT_READY_LOCK ) ;
496
+ let _ = paths:: remove_file ( & ok_file) ;
497
+ Self { ok_file }
498
+ }
499
+
500
+ fn mark_ok ( self ) -> CargoResult < ( ) > {
501
+ let _ = paths:: create ( self . ok_file ) ?;
502
+ Ok ( ( ) )
503
+ }
504
+ }
505
+
482
506
/// Constructs an absolute URL for a child submodule URL with its parent base URL.
483
507
///
484
508
/// Git only assumes a submodule URL is a relative path if it starts with `./`
0 commit comments