commit_packed_refs(): report errors rather than dying

Report errors via a `struct strbuf *err` rather than by calling `die()`. To enable this goal, change `write_packed_entry()` to report errors via a return value and `errno` rather than dying. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Jun 23, 2017 at 09:01 UTC 3478983b517bd62cf2a5c9523815e5e5318a9477
3 files changed +61 -36
refs/files-backend.c
+5 -5
@@ -1094,6 +1094,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
1094 struct ref_iterator *iter;
1095 int ok;
1096 struct ref_to_prune *refs_to_prune = NULL;
1097 + struct strbuf err = STRBUF_INIT;
1098
1099 lock_packed_refs(refs->packed_ref_store, LOCK_DIE_ON_ERROR);
1100
@@ -1128,10 +1129,11 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
1129 if (ok != ITER_DONE)
1130 die("error while iterating over references");
1131
1131 - if (commit_packed_refs(refs->packed_ref_store))
1132 - die_errno("unable to overwrite old ref-pack file");
1132 + if (commit_packed_refs(refs->packed_ref_store, &err))
1133 + die("unable to overwrite old ref-pack file: %s", err.buf);
1134
1135 prune_refs(refs, refs_to_prune);
1136 + strbuf_release(&err);
1137 return 0;
1138 }
1139
@@ -2693,9 +2695,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
2695 &update->new_oid);
2696 }
2697
2696 - if (commit_packed_refs(refs->packed_ref_store)) {
2697 - strbuf_addf(err, "unable to commit packed-refs file: %s",
2698 - strerror(errno));
2698 + if (commit_packed_refs(refs->packed_ref_store, err)) {
2699 ret = TRANSACTION_GENERIC_ERROR;
2700 goto cleanup;
2701 }
refs/packed-backend.c
+55 -30
@@ -493,15 +493,19 @@ static struct ref_iterator *packed_ref_iterator_begin(
493
494 /*
495 * Write an entry to the packed-refs file for the specified refname.
496 - * If peeled is non-NULL, write it as the entry's peeled value.
496 + * If peeled is non-NULL, write it as the entry's peeled value. On
497 + * error, return a nonzero value and leave errno set at the value left
498 + * by the failing call to `fprintf()`.
499 */
498 -static void write_packed_entry(FILE *fh, const char *refname,
499 - const unsigned char *sha1,
500 - const unsigned char *peeled)
500 +static int write_packed_entry(FILE *fh, const char *refname,
501 + const unsigned char *sha1,
502 + const unsigned char *peeled)
503 {
502 - fprintf_or_die(fh, "%s %s\n", sha1_to_hex(sha1), refname);
503 - if (peeled)
504 - fprintf_or_die(fh, "^%s\n", sha1_to_hex(peeled));
504 + if (fprintf(fh, "%s %s\n", sha1_to_hex(sha1), refname) < 0 ||
505 + (peeled && fprintf(fh, "^%s\n", sha1_to_hex(peeled)) < 0))
506 + return -1;
507 +
508 + return 0;
509 }
510
511 int lock_packed_refs(struct ref_store *ref_store, int flags)
@@ -550,49 +554,74 @@ static const char PACKED_REFS_HEADER[] =
554 /*
555 * Write the current version of the packed refs cache from memory to
556 * disk. The packed-refs file must already be locked for writing (see
553 - * lock_packed_refs()). Return zero on success. On errors, set errno
554 - * and return a nonzero value.
557 + * lock_packed_refs()). Return zero on success. On errors, rollback
558 + * the lockfile, write an error message to `err`, and return a nonzero
559 + * value.
560 */
556 -int commit_packed_refs(struct ref_store *ref_store)
561 +int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
562 {
563 struct packed_ref_store *refs =
564 packed_downcast(ref_store, REF_STORE_WRITE | REF_STORE_MAIN,
565 "commit_packed_refs");
566 struct packed_ref_cache *packed_ref_cache =
567 get_packed_ref_cache(refs);
563 - int ok, error = 0;
564 - int save_errno = 0;
568 + int ok;
569 + int ret = -1;
570 FILE *out;
571 struct ref_iterator *iter;
572
573 if (!is_lock_file_locked(&refs->lock))
569 - die("BUG: packed-refs not locked");
574 + die("BUG: commit_packed_refs() called when unlocked");
575
576 out = fdopen_lock_file(&refs->lock, "w");
572 - if (!out)
573 - die_errno("unable to fdopen packed-refs descriptor");
577 + if (!out) {
578 + strbuf_addf(err, "unable to fdopen packed-refs tempfile: %s",
579 + strerror(errno));
580 + goto error;
581 + }
582
575 - fprintf_or_die(out, "%s", PACKED_REFS_HEADER);
583 + if (fprintf(out, "%s", PACKED_REFS_HEADER) < 0) {
584 + strbuf_addf(err, "error writing to %s: %s",
585 + get_lock_file_path(&refs->lock), strerror(errno));
586 + goto error;
587 + }
588
589 iter = cache_ref_iterator_begin(packed_ref_cache->cache, NULL, 0);
590 while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
591 struct object_id peeled;
592 int peel_error = ref_iterator_peel(iter, &peeled);
593
582 - write_packed_entry(out, iter->refname, iter->oid->hash,
583 - peel_error ? NULL : peeled.hash);
594 + if (write_packed_entry(out, iter->refname, iter->oid->hash,
595 + peel_error ? NULL : peeled.hash)) {
596 + strbuf_addf(err, "error writing to %s: %s",
597 + get_lock_file_path(&refs->lock),
598 + strerror(errno));
599 + ref_iterator_abort(iter);
600 + goto error;
601 + }
602 }
603
586 - if (ok != ITER_DONE)
587 - die("error while iterating over references");
604 + if (ok != ITER_DONE) {
605 + strbuf_addf(err, "unable to write packed-refs file: "
606 + "error iterating over old contents");
607 + goto error;
608 + }
609
610 if (commit_lock_file(&refs->lock)) {
590 - save_errno = errno;
591 - error = -1;
611 + strbuf_addf(err, "error overwriting %s: %s",
612 + refs->path, strerror(errno));
613 + goto out;
614 }
615 +
616 + ret = 0;
617 + goto out;
618 +
619 +error:
620 + rollback_lock_file(&refs->lock);
621 +
622 +out:
623 release_packed_ref_cache(packed_ref_cache);
594 - errno = save_errno;
595 - return error;
624 + return ret;
625 }
626
627 /*
@@ -628,7 +657,7 @@ int repack_without_refs(struct ref_store *ref_store,
657 "repack_without_refs");
658 struct ref_dir *packed;
659 struct string_list_item *refname;
631 - int ret, needs_repacking = 0, removed = 0;
660 + int needs_repacking = 0, removed = 0;
661
662 packed_assert_main_repository(refs, "repack_without_refs");
663 assert(err);
@@ -665,11 +694,7 @@ int repack_without_refs(struct ref_store *ref_store,
694 }
695
696 /* Write what remains */
668 - ret = commit_packed_refs(&refs->base);
669 - if (ret)
670 - strbuf_addf(err, "unable to overwrite old ref-pack file: %s",
671 - strerror(errno));
672 - return ret;
697 + return commit_packed_refs(&refs->base, err);
698 }
699
700 static int packed_init_db(struct ref_store *ref_store, struct strbuf *err)
refs/packed-backend.h
+1 -1
@@ -14,7 +14,7 @@ int lock_packed_refs(struct ref_store *ref_store, int flags);
14 void add_packed_ref(struct ref_store *ref_store,
15 const char *refname, const struct object_id *oid);
16
17 -int commit_packed_refs(struct ref_store *ref_store);
17 +int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err);
18
19 int repack_without_refs(struct ref_store *ref_store,
20 struct string_list *refnames, struct strbuf *err);