diff options
| author | Junio C Hamano <gitster@pobox.com> | 2016-07-25 14:13:32 -0700 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2016-07-25 14:13:33 -0700 | 
| commit | 702ebbf4e2937accbac8184f87932f961e626a63 (patch) | |
| tree | ee668108dd4b224862b59bcc978b464b8ae2b58b /refs/files-backend.c | |
| parent | 6b34ce90a748ff6bd679c29bc3f37a75a1bd3441 (diff) | |
| parent | 841caad903f2b160e9f5ff05f961d20ad9085ddc (diff) | |
Merge branch 'mh/update-ref-errors'
Error handling in the codepaths that updates refs has been
improved.
* mh/update-ref-errors:
  lock_ref_for_update(): avoid a symref resolution
  lock_ref_for_update(): make error handling more uniform
  t1404: add more tests of update-ref error handling
  t1404: document function test_update_rejected
  t1404: remove "prefix" argument to test_update_rejected
  t1404: rename file to t1404-update-ref-errors.sh
Diffstat (limited to 'refs/files-backend.c')
| -rw-r--r-- | refs/files-backend.c | 74 | 
1 files changed, 42 insertions, 32 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c index 4dd72b42c8..1bf643025c 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -3389,6 +3389,38 @@ static const char *original_update_refname(struct ref_update *update)  }  /* + * Check whether the REF_HAVE_OLD and old_oid values stored in update + * are consistent with oid, which is the reference's current value. If + * everything is OK, return 0; otherwise, write an error message to + * err and return -1. + */ +static int check_old_oid(struct ref_update *update, struct object_id *oid, +			 struct strbuf *err) +{ +	if (!(update->flags & REF_HAVE_OLD) || +		   !hashcmp(oid->hash, update->old_sha1)) +		return 0; + +	if (is_null_sha1(update->old_sha1)) +		strbuf_addf(err, "cannot lock ref '%s': " +			    "reference already exists", +			    original_update_refname(update)); +	else if (is_null_oid(oid)) +		strbuf_addf(err, "cannot lock ref '%s': " +			    "reference is missing but expected %s", +			    original_update_refname(update), +			    sha1_to_hex(update->old_sha1)); +	else +		strbuf_addf(err, "cannot lock ref '%s': " +			    "is at %s but expected %s", +			    original_update_refname(update), +			    oid_to_hex(oid), +			    sha1_to_hex(update->old_sha1)); + +	return -1; +} + +/*   * Prepare for carrying out update:   * - Lock the reference referred to by update.   * - Read the reference under lock. @@ -3433,7 +3465,7 @@ static int lock_ref_for_update(struct ref_update *update,  		reason = strbuf_detach(err, NULL);  		strbuf_addf(err, "cannot lock ref '%s': %s", -			    update->refname, reason); +			    original_update_refname(update), reason);  		free(reason);  		return ret;  	} @@ -3447,28 +3479,17 @@ static int lock_ref_for_update(struct ref_update *update,  			 * the transaction, so we have to read it here  			 * to record and possibly check old_sha1:  			 */ -			if (read_ref_full(update->refname, -					  mustexist ? RESOLVE_REF_READING : 0, +			if (read_ref_full(referent.buf, 0,  					  lock->old_oid.hash, NULL)) {  				if (update->flags & REF_HAVE_OLD) {  					strbuf_addf(err, "cannot lock ref '%s': " -						    "can't resolve old value", -						    update->refname); -					return TRANSACTION_GENERIC_ERROR; -				} else { -					hashclr(lock->old_oid.hash); +						    "error reading reference", +						    original_update_refname(update)); +					return -1;  				} -			} -			if ((update->flags & REF_HAVE_OLD) && -			    hashcmp(lock->old_oid.hash, update->old_sha1)) { -				strbuf_addf(err, "cannot lock ref '%s': " -					    "is at %s but expected %s", -					    update->refname, -					    sha1_to_hex(lock->old_oid.hash), -					    sha1_to_hex(update->old_sha1)); +			} else if (check_old_oid(update, &lock->old_oid, err)) {  				return TRANSACTION_GENERIC_ERROR;  			} -  		} else {  			/*  			 * Create a new update for the reference this @@ -3485,6 +3506,9 @@ static int lock_ref_for_update(struct ref_update *update,  	} else {  		struct ref_update *parent_update; +		if (check_old_oid(update, &lock->old_oid, err)) +			return TRANSACTION_GENERIC_ERROR; +  		/*  		 * If this update is happening indirectly because of a  		 * symref update, record the old SHA-1 in the parent @@ -3495,20 +3519,6 @@ static int lock_ref_for_update(struct ref_update *update,  		     parent_update = parent_update->parent_update) {  			oidcpy(&parent_update->lock->old_oid, &lock->old_oid);  		} - -		if ((update->flags & REF_HAVE_OLD) && -		    hashcmp(lock->old_oid.hash, update->old_sha1)) { -			if (is_null_sha1(update->old_sha1)) -				strbuf_addf(err, "cannot lock ref '%s': reference already exists", -					    original_update_refname(update)); -			else -				strbuf_addf(err, "cannot lock ref '%s': is at %s but expected %s", -					    original_update_refname(update), -					    sha1_to_hex(lock->old_oid.hash), -					    sha1_to_hex(update->old_sha1)); - -			return TRANSACTION_GENERIC_ERROR; -		}  	}  	if ((update->flags & REF_HAVE_NEW) && @@ -3530,7 +3540,7 @@ static int lock_ref_for_update(struct ref_update *update,  			 */  			update->lock = NULL;  			strbuf_addf(err, -				    "cannot update the ref '%s': %s", +				    "cannot update ref '%s': %s",  				    update->refname, write_err);  			free(write_err);  			return TRANSACTION_GENERIC_ERROR;  | 
