prune_refs(): use delete_refs()
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 26d1ac1e32eb4fc4c6729abcf0354dbad6177d1b..e40989431fc6c5adaaf23de59dedc65e62306470 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2801,15 +2801,23 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
        return 0;
 }
 
-int delete_ref(const char *refname, const unsigned char *sha1, unsigned int flags)
+int delete_ref(const char *refname, const unsigned char *old_sha1,
+              unsigned int flags)
 {
        struct ref_transaction *transaction;
        struct strbuf err = STRBUF_INIT;
 
+       /*
+        * Treat NULL_SHA1 and NULL alike, to mean "we don't care what
+        * the old value of the reference was (or even if it didn't
+        * exist)":
+        */
+       if (old_sha1 && is_null_sha1(old_sha1))
+               old_sha1 = NULL;
+
        transaction = ref_transaction_begin(&err);
        if (!transaction ||
-           ref_transaction_delete(transaction, refname,
-                                  (sha1 && !is_null_sha1(sha1)) ? sha1 : NULL,
+           ref_transaction_delete(transaction, refname, old_sha1,
                                   flags, NULL, &err) ||
            ref_transaction_commit(transaction, &err)) {
                error("%s", err.buf);
@@ -2822,6 +2830,44 @@ int delete_ref(const char *refname, const unsigned char *sha1, unsigned int flag
        return 0;
 }
 
+int delete_refs(struct string_list *refnames)
+{
+       struct strbuf err = STRBUF_INIT;
+       int i, result = 0;
+
+       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;
+
+               if (delete_ref(refname, NULL, 0))
+                       result |= error(_("could not remove reference %s"), refname);
+       }
+
+out:
+       strbuf_release(&err);
+       return result;
+}
+
 /*
  * People using contrib's git-new-workdir have .git/logs/refs ->
  * /some/other/path/.git/logs/refs, and that may live on another device.