When deleting a ref through a symref (e.g. using 'git update-ref -d HEAD'
to delete refs/heads/master), the packed version of that ref would not
be deleted, because delete_ref() would pass the symref name (as opposed
to the dereferenced ref name) to repack_without_ref().

This patch revamps the logic in delete_ref() to make it easier to read,
and to clarify how it operates when given a symref.

Signed-off-by: Johan Herland <jo...@herland.net>
---
 refs.c                | 33 +++++++++++++++++----------------
 t/t1400-update-ref.sh |  2 +-
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/refs.c b/refs.c
index da74a2b..df4fe20 100644
--- a/refs.c
+++ b/refs.c
@@ -1751,34 +1751,35 @@ static int repack_without_ref(const char *refname)
 int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
 {
        struct ref_lock *lock;
-       int err, i = 0, ret = 0, flag = 0;
+       int err, delete_symref, ret = 0, flag = 0;
 
        lock = lock_ref_sha1_basic(refname, sha1, 0, &flag);
        if (!lock)
                return 1;
-       if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) {
-               /* loose */
-               const char *path;
 
-               if (!(delopt & REF_NODEREF)) {
-                       i = strlen(lock->lk->filename) - 5; /* .lock */
-                       lock->lk->filename[i] = 0;
-                       path = lock->lk->filename;
-               } else {
-                       path = git_path("%s", refname);
-               }
-               err = unlink_or_warn(path);
+       /* The following variables are at play here:
+        *  - refname may be a symref (in this case lock->orig_ref_name holds
+        *    the symref name, and lock->ref_name holds the dereferenced name)
+        *  - The dereferenced ref name (lock->ref_name) may be a loose ref, a
+        *    packed ref, or both.
+        *  - If REF_NODEREF is enabled - and refname is a symref, we should
+        *    delete the symref; otherwise delete the dereferenced ref.
+        */
+       delete_symref = (flag & REF_ISSYMREF && delopt & REF_NODEREF);
+       refname = delete_symref ? lock->orig_ref_name : lock->ref_name;
+
+       if (!(flag & REF_ISPACKED) || delete_symref) {
+               /* loose */
+               err = unlink_or_warn(git_path("%s", refname));
                if (err && errno != ENOENT)
                        ret = 1;
-
-               if (!(delopt & REF_NODEREF))
-                       lock->lk->filename[i] = '.';
        }
        /* removing the loose one could have resurrected an earlier
         * packed one.  Also, if it was not loose we need to repack
         * without it.
         */
-       ret |= repack_without_ref(refname);
+       if (!delete_symref)
+               ret |= repack_without_ref(refname);
 
        unlink_or_warn(git_path("logs/%s", lock->ref_name));
        invalidate_ref_cache(NULL);
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index f7ec203..e415ee0 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -85,7 +85,7 @@ test_expect_success \
        "move $m (by HEAD)" \
        "git update-ref HEAD $B $A &&
         test $B"' = $(cat .git/'"$m"')'
-test_expect_failure "delete $m (by HEAD) should remove both packed and loose 
$m" '
+test_expect_success "delete $m (by HEAD) should remove both packed and loose 
$m" '
        git update-ref -d HEAD $B &&
        ! grep "$m" .git/packed-refs &&
        ! test -f .git/$m
-- 
1.7.12.1.609.g5cd6968

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to