@@ -68,6 +68,13 @@ struct packed_ref_store {
6868 * thus the enclosing `packed_ref_store`) must not be freed.
6969 */
7070 struct lock_file lock ;
71+
72+ /*
73+ * Temporary file used when rewriting new contents to the
74+ * "packed-refs" file. Note that this (and thus the enclosing
75+ * `packed_ref_store`) must not be freed.
76+ */
77+ struct tempfile tempfile ;
7178};
7279
7380struct ref_store * packed_ref_store_create (const char * path ,
@@ -522,10 +529,16 @@ int lock_packed_refs(struct ref_store *ref_store, int flags)
522529 timeout_configured = 1 ;
523530 }
524531
532+ /*
533+ * Note that we close the lockfile immediately because we
534+ * don't write new content to it, but rather to a separate
535+ * tempfile.
536+ */
525537 if (hold_lock_file_for_update_timeout (
526538 & refs -> lock ,
527539 refs -> path ,
528- flags , timeout_value ) < 0 )
540+ flags , timeout_value ) < 0 ||
541+ close_lock_file (& refs -> lock ))
529542 return -1 ;
530543
531544 /*
@@ -567,13 +580,23 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
567580 get_packed_ref_cache (refs );
568581 int ok ;
569582 int ret = -1 ;
583+ struct strbuf sb = STRBUF_INIT ;
570584 FILE * out ;
571585 struct ref_iterator * iter ;
572586
573587 if (!is_lock_file_locked (& refs -> lock ))
574588 die ("BUG: commit_packed_refs() called when unlocked" );
575589
576- out = fdopen_lock_file (& refs -> lock , "w" );
590+ strbuf_addf (& sb , "%s.new" , refs -> path );
591+ if (create_tempfile (& refs -> tempfile , sb .buf ) < 0 ) {
592+ strbuf_addf (err , "unable to create file %s: %s" ,
593+ sb .buf , strerror (errno ));
594+ strbuf_release (& sb );
595+ goto out ;
596+ }
597+ strbuf_release (& sb );
598+
599+ out = fdopen_tempfile (& refs -> tempfile , "w" );
577600 if (!out ) {
578601 strbuf_addf (err , "unable to fdopen packed-refs tempfile: %s" ,
579602 strerror (errno ));
@@ -582,7 +605,7 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
582605
583606 if (fprintf (out , "%s" , PACKED_REFS_HEADER ) < 0 ) {
584607 strbuf_addf (err , "error writing to %s: %s" ,
585- get_lock_file_path (& refs -> lock ), strerror (errno ));
608+ get_tempfile_path (& refs -> tempfile ), strerror (errno ));
586609 goto error ;
587610 }
588611
@@ -594,21 +617,21 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
594617 if (write_packed_entry (out , iter -> refname , iter -> oid -> hash ,
595618 peel_error ? NULL : peeled .hash )) {
596619 strbuf_addf (err , "error writing to %s: %s" ,
597- get_lock_file_path (& refs -> lock ),
620+ get_tempfile_path (& refs -> tempfile ),
598621 strerror (errno ));
599622 ref_iterator_abort (iter );
600623 goto error ;
601624 }
602625 }
603626
604627 if (ok != ITER_DONE ) {
605- strbuf_addf (err , "unable to write packed-refs file: "
628+ strbuf_addf (err , "unable to rewrite packed-refs file: "
606629 "error iterating over old contents" );
607630 goto error ;
608631 }
609632
610- if (commit_lock_file (& refs -> lock )) {
611- strbuf_addf (err , "error overwriting %s: %s" ,
633+ if (rename_tempfile (& refs -> tempfile , refs -> path )) {
634+ strbuf_addf (err , "error replacing %s: %s" ,
612635 refs -> path , strerror (errno ));
613636 goto out ;
614637 }
@@ -617,9 +640,10 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
617640 goto out ;
618641
619642error :
620- rollback_lock_file (& refs -> lock );
643+ delete_tempfile (& refs -> tempfile );
621644
622645out :
646+ rollback_lock_file (& refs -> lock );
623647 release_packed_ref_cache (packed_ref_cache );
624648 return ret ;
625649}
0 commit comments