diff options
author | Ronnie Sahlberg <sahlberg@google.com> | 2014-11-03 08:55:57 -0800 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2014-11-03 11:18:35 -0800 |
commit | 986781fccb2eba058d11b432e5c5c6259989981d (patch) | |
tree | 6043e6d0f478d13650f54b81b01d213ddf9972fe | |
parent | 6a0103dc112c3f8c0d3e3f401fbd33ea6e273b31 (diff) | |
download | git-986781fccb2eba058d11b432e5c5c6259989981d.tar.gz |
refs.c: allow deleting refs with a broken sha1rs/ref-transaction-reflog
Add back support to make it possible to delete refs that have a broken
sha1.
Add new internal flags REF_ALLOW_BROKEN and RESOLVE_REF_ALLOW_BAD_SHA1
to pass intent from branch.c that we are willing to allow
resolve_ref_unsafe and lock_ref_sha1_basic to allow broken refs.
Since these refs can not actually be resolved to a sha1, they instead resolve
to null_sha1 when these flags are used.
For example, the ref:
echo "Broken ref" > .git/refs/heads/foo-broken-1
can now be deleted using git branch -d foo-broken-1
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | builtin/branch.c | 5 | ||||
-rw-r--r-- | cache.h | 7 | ||||
-rw-r--r-- | refs.c | 6 | ||||
-rw-r--r-- | refs.h | 6 | ||||
-rwxr-xr-x | t/t1402-check-ref-format.sh | 8 |
5 files changed, 28 insertions, 4 deletions
diff --git a/builtin/branch.c b/builtin/branch.c index 3b79c5087f..04f57d441f 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -238,7 +238,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, target = resolve_ref_unsafe(name, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE - | RESOLVE_REF_ALLOW_BAD_NAME, + | RESOLVE_REF_ALLOW_BAD_NAME + | RESOLVE_REF_ALLOW_BAD_SHA1, sha1, &flags); if (!target) { error(remote_branch @@ -255,7 +256,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, continue; } - if (delete_ref(name, sha1, REF_NODEREF)) { + if (delete_ref(name, sha1, REF_NODEREF|REF_ALLOW_BROKEN)) { error(remote_branch ? _("Error deleting remote branch '%s'") : _("Error deleting branch '%s'"), @@ -1000,10 +1000,17 @@ extern int read_ref(const char *refname, unsigned char *sha1); * resolved. The function returns NULL for such ref names. * Caps and underscores refers to the special refs, such as HEAD, * FETCH_HEAD and friends, that all live outside of the refs/ directory. + * + * RESOLVE_REF_ALLOW_BAD_SHA1 when this flag is set and the ref contains + * an invalid sha1, resolve_ref_unsafe will clear the sha1 argument, + * set the REF_ISBROKEN flag and return the refname. + * This allows using resolve_ref_unsafe to check for existence of such + * broken refs. */ #define RESOLVE_REF_READING 0x01 #define RESOLVE_REF_NO_RECURSE 0x02 #define RESOLVE_REF_ALLOW_BAD_NAME 0x04 +#define RESOLVE_REF_ALLOW_BAD_SHA1 0x08 extern const char *resolve_ref_unsafe(const char *ref, int resolve_flags, unsigned char *sha1, int *flags); extern char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags); @@ -1584,6 +1584,10 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned (buffer[40] != '\0' && !isspace(buffer[40]))) { if (flags) *flags |= REF_ISBROKEN; + if (resolve_flags & RESOLVE_REF_ALLOW_BAD_SHA1) { + hashclr(sha1); + return refname; + } errno = EINVAL; return NULL; } @@ -2265,6 +2269,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname, if (flags & REF_NODEREF) resolve_flags |= RESOLVE_REF_NO_RECURSE; } + if (flags & REF_ALLOW_BROKEN) + resolve_flags |= RESOLVE_REF_ALLOW_BAD_SHA1; refname = resolve_ref_unsafe(refname, resolve_flags, lock->old_sha1, &type); @@ -185,11 +185,13 @@ extern int peel_ref(const char *refname, unsigned char *sha1); * REF_NODEREF: act on the ref directly, instead of dereferencing * symbolic references. * REF_DELETING: tolerate broken refs + * REF_ALLOW_BROKEN: allow locking refs that are broken. * * Flags >= 0x100 are reserved for internal use. */ -#define REF_NODEREF 0x01 -#define REF_DELETING 0x02 +#define REF_NODEREF 0x01 +#define REF_DELETING 0x02 +#define REF_ALLOW_BROKEN 0x04 /** Reads log for the value of ref during at_time. **/ extern int read_ref_at(const char *refname, unsigned int flags, diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index e5dc62e9ef..a0aef69ef2 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -197,4 +197,12 @@ invalid_ref_normalized 'heads///foo.lock' invalid_ref_normalized 'foo.lock/bar' invalid_ref_normalized 'foo.lock///bar' +test_expect_success 'git branch -d can delete ref with broken sha1' ' + echo "012brokensha1" > .git/refs/heads/brokensha1 && + test_when_finished "rm -f .git/refs/heads/brokensha1" && + git branch -d brokensha1 && + git branch >output && + ! grep -e "brokensha1" output +' + test_done |