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 <mhag...@alum.mit.edu>
---
 refs/files-backend.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/refs/files-backend.c b/refs/files-backend.c
index 4f4c47b9db..36f81b4f28 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -2630,6 +2630,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.
         *
@@ -2666,20 +2687,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:
-- 
2.14.1

Reply via email to