delete_refs(): bail early if the packed-refs file cannot be rewritten
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index cebabc5cd4bce8615487f512f73db704c7b1b9fb..e40989431fc6c5adaaf23de59dedc65e62306470 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2835,9 +2835,26 @@ int delete_refs(struct string_list *refnames)
        struct strbuf err = STRBUF_INIT;
        int i, result = 0;
 
-       if (repack_without_refs(refnames, &err))
-               result |= error("%s", err.buf);
-       strbuf_release(&err);
+       if (!refnames->nr)
+               return 0;
+
+       result = repack_without_refs(refnames, &err);
+       if (result) {
+               /*
+                * If we failed to rewrite the packed-refs file, then
+                * it is unsafe to try to remove loose refs, because
+                * doing so might expose an obsolete packed value for
+                * a reference that might even point at an object that
+                * has been garbage collected.
+                */
+               if (refnames->nr == 1)
+                       error(_("could not delete reference %s: %s"),
+                             refnames->items[0].string, err.buf);
+               else
+                       error(_("could not delete references: %s"), err.buf);
+
+               goto out;
+       }
 
        for (i = 0; i < refnames->nr; i++) {
                const char *refname = refnames->items[i].string;
@@ -2846,6 +2863,8 @@ int delete_refs(struct string_list *refnames)
                        result |= error(_("could not remove reference %s"), refname);
        }
 
+out:
+       strbuf_release(&err);
        return result;
 }