From a5e2499e5421c88ec2403087597613d60b8f3077 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Sat, 23 May 2015 01:34:53 +0200 Subject: [PATCH 1/5] verify_lock(): return 0/-1 rather than struct ref_lock * Its return value wasn't conveying any extra information, but it made the reader wonder whether the ref_lock that it returned might be different than the one that was passed to it. So change the function to the traditional "return 0 on success or a negative value on error". Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- refs.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/refs.c b/refs.c index 8480d8dbf5..27b769afdd 100644 --- a/refs.c +++ b/refs.c @@ -2218,9 +2218,14 @@ static void unlock_ref(struct ref_lock *lock) free(lock); } -/* This function should make sure errno is meaningful on error */ -static struct ref_lock *verify_lock(struct ref_lock *lock, - const unsigned char *old_sha1, int mustexist) +/* + * Verify that the reference locked by lock has the value old_sha1. + * Fail if the reference doesn't exist and mustexist is set. Return 0 + * on success or a negative value on error. This function should make + * sure errno is meaningful on error. + */ +static int verify_lock(struct ref_lock *lock, + const unsigned char *old_sha1, int mustexist) { if (read_ref_full(lock->ref_name, mustexist ? RESOLVE_REF_READING : 0, @@ -2229,16 +2234,16 @@ static struct ref_lock *verify_lock(struct ref_lock *lock, error("Can't verify ref %s", lock->ref_name); unlock_ref(lock); errno = save_errno; - return NULL; + return -1; } if (hashcmp(lock->old_sha1, old_sha1)) { error("Ref %s is at %s but expected %s", lock->ref_name, sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1)); unlock_ref(lock); errno = EBUSY; - return NULL; + return -1; } - return lock; + return 0; } static int remove_empty_directories(const char *file) @@ -2466,7 +2471,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname, goto error_return; } } - return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock; + if (old_sha1 && verify_lock(lock, old_sha1, mustexist)) + return NULL; + return lock; error_return: unlock_ref(lock); From f41d6329704a8c3f7286f52c3589d381ac0bc79d Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Sat, 23 May 2015 01:34:54 +0200 Subject: [PATCH 2/5] verify_lock(): on errors, let the caller unlock the lock The caller already knows how to do it, so always do it in the same place. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- refs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/refs.c b/refs.c index 27b769afdd..af49e5cbaa 100644 --- a/refs.c +++ b/refs.c @@ -2232,14 +2232,12 @@ static int verify_lock(struct ref_lock *lock, lock->old_sha1, NULL)) { int save_errno = errno; error("Can't verify ref %s", lock->ref_name); - unlock_ref(lock); errno = save_errno; return -1; } if (hashcmp(lock->old_sha1, old_sha1)) { error("Ref %s is at %s but expected %s", lock->ref_name, sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1)); - unlock_ref(lock); errno = EBUSY; return -1; } @@ -2471,8 +2469,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname, goto error_return; } } - if (old_sha1 && verify_lock(lock, old_sha1, mustexist)) - return NULL; + if (old_sha1 && verify_lock(lock, old_sha1, mustexist)) { + last_errno = errno; + goto error_return; + } return lock; error_return: From 33ffc176d65e1e98e1eea262dc7827830c33c56d Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Sat, 23 May 2015 01:34:55 +0200 Subject: [PATCH 3/5] verify_lock(): report errors via a strbuf Instead of writing error messages directly to stderr, write them to a "strbuf *err". The caller, lock_ref_sha1_basic(), uses this error reporting convention with all the other callees, and reports its error this way to its callers. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- refs.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/refs.c b/refs.c index af49e5cbaa..3a73cf2f16 100644 --- a/refs.c +++ b/refs.c @@ -2221,23 +2221,28 @@ static void unlock_ref(struct ref_lock *lock) /* * Verify that the reference locked by lock has the value old_sha1. * Fail if the reference doesn't exist and mustexist is set. Return 0 - * on success or a negative value on error. This function should make - * sure errno is meaningful on error. + * on success. On error, write an error message to err, set errno, and + * return a negative value. */ static int verify_lock(struct ref_lock *lock, - const unsigned char *old_sha1, int mustexist) + const unsigned char *old_sha1, int mustexist, + struct strbuf *err) { + assert(err); + if (read_ref_full(lock->ref_name, mustexist ? RESOLVE_REF_READING : 0, lock->old_sha1, NULL)) { int save_errno = errno; - error("Can't verify ref %s", lock->ref_name); + strbuf_addf(err, "Can't verify ref %s", lock->ref_name); errno = save_errno; return -1; } if (hashcmp(lock->old_sha1, old_sha1)) { - error("Ref %s is at %s but expected %s", lock->ref_name, - sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1)); + strbuf_addf(err, "Ref %s is at %s but expected %s", + lock->ref_name, + sha1_to_hex(lock->old_sha1), + sha1_to_hex(old_sha1)); errno = EBUSY; return -1; } @@ -2469,7 +2474,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname, goto error_return; } } - if (old_sha1 && verify_lock(lock, old_sha1, mustexist)) { + if (old_sha1 && verify_lock(lock, old_sha1, mustexist, err)) { last_errno = errno; goto error_return; } From 000f0da57aca00d6ff960f0763dee73c34cd7677 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Sat, 23 May 2015 01:34:56 +0200 Subject: [PATCH 4/5] verify_lock(): do not capitalize error messages Our convention is for error messages to start with a lower-case letter. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- refs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/refs.c b/refs.c index 3a73cf2f16..2af4188ea4 100644 --- a/refs.c +++ b/refs.c @@ -2234,12 +2234,12 @@ static int verify_lock(struct ref_lock *lock, mustexist ? RESOLVE_REF_READING : 0, lock->old_sha1, NULL)) { int save_errno = errno; - strbuf_addf(err, "Can't verify ref %s", lock->ref_name); + strbuf_addf(err, "can't verify ref %s", lock->ref_name); errno = save_errno; return -1; } if (hashcmp(lock->old_sha1, old_sha1)) { - strbuf_addf(err, "Ref %s is at %s but expected %s", + strbuf_addf(err, "ref %s is at %s but expected %s", lock->ref_name, sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1)); From c2e0a718c66760efebf7b348aef48dc1f885bc2a Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Sat, 23 May 2015 01:34:57 +0200 Subject: [PATCH 5/5] ref_transaction_commit(): do not capitalize error messages Our convention is for error messages to start with a lower-case letter. Signed-off-by: Michael Haggerty Signed-off-by: Junio C Hamano --- refs.c | 4 ++-- t/t1400-update-ref.sh | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/refs.c b/refs.c index 2af4188ea4..6ae81e9744 100644 --- a/refs.c +++ b/refs.c @@ -3922,7 +3922,7 @@ int ref_transaction_commit(struct ref_transaction *transaction, ? TRANSACTION_NAME_CONFLICT : TRANSACTION_GENERIC_ERROR; reason = strbuf_detach(err, NULL); - strbuf_addf(err, "Cannot lock ref '%s': %s", + strbuf_addf(err, "cannot lock ref '%s': %s", update->refname, reason); free(reason); goto cleanup; @@ -3945,7 +3945,7 @@ int ref_transaction_commit(struct ref_transaction *transaction, * write_ref_to_lockfile(): */ update->lock = NULL; - strbuf_addf(err, "Cannot update the ref '%s'.", + strbuf_addf(err, "cannot update the ref '%s'.", update->refname); ret = TRANSACTION_GENERIC_ERROR; goto cleanup; diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index ba89f4c009..d787bf50f8 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -519,7 +519,7 @@ test_expect_success 'stdin create ref works with path with space to blob' ' test_expect_success 'stdin update ref fails with wrong old value' ' echo "update $c $m $m~1" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: Cannot lock ref '"'"'$c'"'"'" err && + grep "fatal: cannot lock ref '"'"'$c'"'"'" err && test_must_fail git rev-parse --verify -q $c ' @@ -555,7 +555,7 @@ test_expect_success 'stdin update ref works with right old value' ' test_expect_success 'stdin delete ref fails with wrong old value' ' echo "delete $a $m~1" >stdin && test_must_fail git update-ref --stdin err && - grep "fatal: Cannot lock ref '"'"'$a'"'"'" err && + grep "fatal: cannot lock ref '"'"'$a'"'"'" err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual @@ -688,7 +688,7 @@ test_expect_success 'stdin update refs fails with wrong old value' ' update $c '' EOF test_must_fail git update-ref --stdin err && - grep "fatal: Cannot lock ref '"'"'$c'"'"'" err && + grep "fatal: cannot lock ref '"'"'$c'"'"'" err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual && @@ -883,7 +883,7 @@ test_expect_success 'stdin -z create ref works with path with space to blob' ' test_expect_success 'stdin -z update ref fails with wrong old value' ' printf $F "update $c" "$m" "$m~1" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: Cannot lock ref '"'"'$c'"'"'" err && + grep "fatal: cannot lock ref '"'"'$c'"'"'" err && test_must_fail git rev-parse --verify -q $c ' @@ -899,7 +899,7 @@ test_expect_success 'stdin -z create ref fails when ref exists' ' git rev-parse "$c" >expect && printf $F "create $c" "$m~1" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: Cannot lock ref '"'"'$c'"'"'" err && + grep "fatal: cannot lock ref '"'"'$c'"'"'" err && git rev-parse "$c" >actual && test_cmp expect actual ' @@ -930,7 +930,7 @@ test_expect_success 'stdin -z update ref works with right old value' ' test_expect_success 'stdin -z delete ref fails with wrong old value' ' printf $F "delete $a" "$m~1" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: Cannot lock ref '"'"'$a'"'"'" err && + grep "fatal: cannot lock ref '"'"'$a'"'"'" err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual @@ -1045,7 +1045,7 @@ test_expect_success 'stdin -z update refs fails with wrong old value' ' git update-ref $c $m && printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$m" "$Z" >stdin && test_must_fail git update-ref -z --stdin err && - grep "fatal: Cannot lock ref '"'"'$c'"'"'" err && + grep "fatal: cannot lock ref '"'"'$c'"'"'" err && git rev-parse $m >expect && git rev-parse $a >actual && test_cmp expect actual &&