summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Haggerty <mhagger@alum.mit.edu>2017-09-08 15:51:53 +0200
committerJunio C Hamano <gitster@pobox.com>2017-09-09 03:18:04 +0900
commit5e00a6c873981f87165adfecf29ad0ecc2c2c5df (patch)
treefaebf75ef8baa550ec5be76ed261bb7f2b68f97a
parent9939b33d6a3900e76b9cf95cbbb30ad8cf38cab3 (diff)
downloadgit-5e00a6c873981f87165adfecf29ad0ecc2c2c5df.tar.gz
files_transaction_finish(): delete reflogs before referencesmh/packed-ref-transactions
If the deletion steps unexpectedly fail, it is less bad to leave a reference without its reflog than it is to leave a reflog without its reference, since the latter is an invalid repository state. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--refs/files-backend.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 29eb5e826f..961424a4ea 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2637,6 +2637,27 @@ static int files_transaction_finish(struct ref_store *ref_store,
}
/*
+ * Now that updates are safely completed, we can perform
+ * deletes. First delete the reflogs of any references that
+ * will be deleted, since (in the unexpected event of an
+ * error) leaving a reference without a reflog is less bad
+ * than leaving a reflog without a reference (the latter is a
+ * mildly invalid repository state):
+ */
+ for (i = 0; i < transaction->nr; i++) {
+ struct ref_update *update = transaction->updates[i];
+ if (update->flags & REF_DELETING &&
+ !(update->flags & REF_LOG_ONLY) &&
+ !(update->flags & REF_ISPRUNING)) {
+ strbuf_reset(&sb);
+ files_reflog_path(refs, &sb, update->refname);
+ if (!unlink_or_warn(sb.buf))
+ try_remove_empty_parents(refs, update->refname,
+ REMOVE_EMPTY_PARENTS_REFLOG);
+ }
+ }
+
+ /*
* Perform deletes now that updates are safely completed.
*
* First delete any packed versions of the references, while
@@ -2672,20 +2693,6 @@ static int files_transaction_finish(struct ref_store *ref_store,
}
}
- /* Delete the reflogs of any references that were deleted: */
- for (i = 0; i < transaction->nr; i++) {
- struct ref_update *update = transaction->updates[i];
- if (update->flags & REF_DELETING &&
- !(update->flags & REF_LOG_ONLY) &&
- !(update->flags & REF_ISPRUNING)) {
- strbuf_reset(&sb);
- files_reflog_path(refs, &sb, update->refname);
- if (!unlink_or_warn(sb.buf))
- try_remove_empty_parents(refs, update->refname,
- REMOVE_EMPTY_PARENTS_REFLOG);
- }
- }
-
clear_loose_ref_cache(refs);
cleanup: