Skip to content

Commit 42dfa7e

Browse files
mhaggergitster
authored andcommitted
commit_packed_refs(): use a staging file separate from the lockfile
We will want to be able to hold the lockfile for `packed-refs` even after we have activated the new values. So use a separate tempfile, `packed-refs.new`, as a place to stage the new contents of the `packed-refs` file. For now this is all done within `commit_packed_refs()`, but that will change shortly. Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3478983 commit 42dfa7e

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

refs/packed-backend.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

7380
struct 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

619642
error:
620-
rollback_lock_file(&refs->lock);
643+
delete_tempfile(&refs->tempfile);
621644

622645
out:
646+
rollback_lock_file(&refs->lock);
623647
release_packed_ref_cache(packed_ref_cache);
624648
return ret;
625649
}

0 commit comments

Comments
 (0)