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);