Merge branch 'mh/tidy-ref-update-flags'

Code clean-up in refs API implementation.

* mh/tidy-ref-update-flags:
  refs: update some more docs to use "oid" rather than "sha1"
  write_packed_entry(): take `object_id` arguments
  refs: rename constant `REF_ISPRUNING` to `REF_IS_PRUNING`
  refs: rename constant `REF_NODEREF` to `REF_NO_DEREF`
  refs: tidy up and adjust visibility of the `ref_update` flags
  ref_transaction_add_update(): remove a check
  ref_transaction_update(): die on disallowed flags
  prune_ref(): call `ref_transaction_add_update()` directly
  files_transaction_prepare(): don't leak flags to packed transaction
This commit is contained in:
Junio C Hamano 2017-11-15 12:14:29 +09:00
commit a97222978a
16 changed files with 189 additions and 163 deletions

View File

@ -1073,7 +1073,7 @@ int bisect_clean_state(void)
struct string_list refs_for_removal = STRING_LIST_INIT_NODUP; struct string_list refs_for_removal = STRING_LIST_INIT_NODUP;
for_each_ref_in("refs/bisect", mark_for_removal, (void *) &refs_for_removal); for_each_ref_in("refs/bisect", mark_for_removal, (void *) &refs_for_removal);
string_list_append(&refs_for_removal, xstrdup("BISECT_HEAD")); string_list_append(&refs_for_removal, xstrdup("BISECT_HEAD"));
result = delete_refs("bisect: remove", &refs_for_removal, REF_NODEREF); result = delete_refs("bisect: remove", &refs_for_removal, REF_NO_DEREF);
refs_for_removal.strdup_strings = 1; refs_for_removal.strdup_strings = 1;
string_list_clear(&refs_for_removal, 0); string_list_clear(&refs_for_removal, 0);
unlink_or_warn(git_path_bisect_expected_rev()); unlink_or_warn(git_path_bisect_expected_rev());

View File

@ -2148,7 +2148,7 @@ static void am_abort(struct am_state *state)
has_curr_head ? &curr_head : NULL, 0, has_curr_head ? &curr_head : NULL, 0,
UPDATE_REFS_DIE_ON_ERR); UPDATE_REFS_DIE_ON_ERR);
else if (curr_branch) else if (curr_branch)
delete_ref(NULL, curr_branch, NULL, REF_NODEREF); delete_ref(NULL, curr_branch, NULL, REF_NO_DEREF);
free(curr_branch); free(curr_branch);
am_destroy(state); am_destroy(state);

View File

@ -258,7 +258,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
} }
if (delete_ref(NULL, name, is_null_oid(&oid) ? NULL : &oid, if (delete_ref(NULL, name, is_null_oid(&oid) ? NULL : &oid,
REF_NODEREF)) { REF_NO_DEREF)) {
error(remote_branch error(remote_branch
? _("Error deleting remote-tracking branch '%s'") ? _("Error deleting remote-tracking branch '%s'")
: _("Error deleting branch '%s'"), : _("Error deleting branch '%s'"),

View File

@ -663,7 +663,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
/* Nothing to do. */ /* Nothing to do. */
} else if (opts->force_detach || !new->path) { /* No longer on any branch. */ } else if (opts->force_detach || !new->path) { /* No longer on any branch. */
update_ref(msg.buf, "HEAD", &new->commit->object.oid, NULL, update_ref(msg.buf, "HEAD", &new->commit->object.oid, NULL,
REF_NODEREF, UPDATE_REFS_DIE_ON_ERR); REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
if (!opts->quiet) { if (!opts->quiet) {
if (old->path && if (old->path &&
advice_detached_head && !opts->force_detach) advice_detached_head && !opts->force_detach)

View File

@ -689,7 +689,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
} else if (our) { } else if (our) {
struct commit *c = lookup_commit_reference(&our->old_oid); struct commit *c = lookup_commit_reference(&our->old_oid);
/* --branch specifies a non-branch (i.e. tags), detach HEAD */ /* --branch specifies a non-branch (i.e. tags), detach HEAD */
update_ref(msg, "HEAD", &c->object.oid, NULL, REF_NODEREF, update_ref(msg, "HEAD", &c->object.oid, NULL, REF_NO_DEREF,
UPDATE_REFS_DIE_ON_ERR); UPDATE_REFS_DIE_ON_ERR);
} else if (remote) { } else if (remote) {
/* /*
@ -697,7 +697,7 @@ static void update_head(const struct ref *our, const struct ref *remote,
* HEAD points to a branch but we don't know which one. * HEAD points to a branch but we don't know which one.
* Detach HEAD in all these cases. * Detach HEAD in all these cases.
*/ */
update_ref(msg, "HEAD", &remote->old_oid, NULL, REF_NODEREF, update_ref(msg, "HEAD", &remote->old_oid, NULL, REF_NO_DEREF,
UPDATE_REFS_DIE_ON_ERR); UPDATE_REFS_DIE_ON_ERR);
} }
} }

View File

@ -686,7 +686,7 @@ static int merge_abort(struct notes_merge_options *o)
if (delete_ref(NULL, "NOTES_MERGE_PARTIAL", NULL, 0)) if (delete_ref(NULL, "NOTES_MERGE_PARTIAL", NULL, 0))
ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL")); ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL"));
if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NODEREF)) if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NO_DEREF))
ret += error(_("failed to delete ref NOTES_MERGE_REF")); ret += error(_("failed to delete ref NOTES_MERGE_REF"));
if (notes_merge_abort(o)) if (notes_merge_abort(o))
ret += error(_("failed to remove 'git notes merge' worktree")); ret += error(_("failed to remove 'git notes merge' worktree"));

View File

@ -693,7 +693,7 @@ static int mv(int argc, const char **argv)
read_ref_full(item->string, RESOLVE_REF_READING, &oid, &flag); read_ref_full(item->string, RESOLVE_REF_READING, &oid, &flag);
if (!(flag & REF_ISSYMREF)) if (!(flag & REF_ISSYMREF))
continue; continue;
if (delete_ref(NULL, item->string, NULL, REF_NODEREF)) if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF))
die(_("deleting '%s' failed"), item->string); die(_("deleting '%s' failed"), item->string);
} }
for (i = 0; i < remote_branches.nr; i++) { for (i = 0; i < remote_branches.nr; i++) {
@ -788,7 +788,7 @@ static int rm(int argc, const char **argv)
strbuf_release(&buf); strbuf_release(&buf);
if (!result) if (!result)
result = delete_refs("remote: remove", &branches, REF_NODEREF); result = delete_refs("remote: remove", &branches, REF_NO_DEREF);
string_list_clear(&branches, 0); string_list_clear(&branches, 0);
if (skipped.nr) { if (skipped.nr) {
@ -1255,7 +1255,7 @@ static int set_head(int argc, const char **argv)
head_name = xstrdup(states.heads.items[0].string); head_name = xstrdup(states.heads.items[0].string);
free_remote_ref_states(&states); free_remote_ref_states(&states);
} else if (opt_d && !opt_a && argc == 1) { } else if (opt_d && !opt_a && argc == 1) {
if (delete_ref(NULL, buf.buf, NULL, REF_NODEREF)) if (delete_ref(NULL, buf.buf, NULL, REF_NO_DEREF))
result |= error(_("Could not delete %s"), buf.buf); result |= error(_("Could not delete %s"), buf.buf);
} else } else
usage_with_options(builtin_remote_sethead_usage, options); usage_with_options(builtin_remote_sethead_usage, options);

View File

@ -58,7 +58,7 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
die("Cannot delete %s, not a symbolic ref", argv[0]); die("Cannot delete %s, not a symbolic ref", argv[0]);
if (!strcmp(argv[0], "HEAD")) if (!strcmp(argv[0], "HEAD"))
die("deleting '%s' is not allowed", argv[0]); die("deleting '%s' is not allowed", argv[0]);
return delete_ref(NULL, argv[0], NULL, REF_NODEREF); return delete_ref(NULL, argv[0], NULL, REF_NO_DEREF);
} }
switch (argc) { switch (argc) {

View File

@ -312,7 +312,7 @@ static const char *parse_cmd_verify(struct ref_transaction *transaction,
static const char *parse_cmd_option(struct strbuf *input, const char *next) static const char *parse_cmd_option(struct strbuf *input, const char *next)
{ {
if (!strncmp(next, "no-deref", 8) && next[8] == line_termination) if (!strncmp(next, "no-deref", 8) && next[8] == line_termination)
update_flags |= REF_NODEREF; update_flags |= REF_NO_DEREF;
else else
die("option unknown: %s", next); die("option unknown: %s", next);
return next + 8; return next + 8;
@ -427,7 +427,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
} }
if (no_deref) if (no_deref)
flags = REF_NODEREF; flags = REF_NO_DEREF;
if (delete) if (delete)
/* /*
* For purposes of backwards compatibility, we treat * For purposes of backwards compatibility, we treat

8
refs.c
View File

@ -770,7 +770,7 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
if (cb->cutoff_cnt) if (cb->cutoff_cnt)
*cb->cutoff_cnt = cb->reccnt - 1; *cb->cutoff_cnt = cb->reccnt - 1;
/* /*
* we have not yet updated cb->[n|o]sha1 so they still * we have not yet updated cb->[n|o]oid so they still
* hold the values for the previous record. * hold the values for the previous record.
*/ */
if (!is_null_oid(&cb->ooid)) { if (!is_null_oid(&cb->ooid)) {
@ -906,9 +906,6 @@ struct ref_update *ref_transaction_add_update(
if (transaction->state != REF_TRANSACTION_OPEN) if (transaction->state != REF_TRANSACTION_OPEN)
die("BUG: update called for transaction that is not open"); die("BUG: update called for transaction that is not open");
if ((flags & REF_ISPRUNING) && !(flags & REF_NODEREF))
die("BUG: REF_ISPRUNING set without REF_NODEREF");
FLEX_ALLOC_STR(update, refname, refname); FLEX_ALLOC_STR(update, refname, refname);
ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc); ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
transaction->updates[transaction->nr++] = update; transaction->updates[transaction->nr++] = update;
@ -940,7 +937,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
return -1; return -1;
} }
flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS; if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0); flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);

77
refs.h
View File

@ -126,7 +126,7 @@ int peel_ref(const char *refname, struct object_id *oid);
/** /**
* Resolve refname in the nested "gitlink" repository in the specified * Resolve refname in the nested "gitlink" repository in the specified
* submodule (which must be non-NULL). If the resolution is * submodule (which must be non-NULL). If the resolution is
* successful, return 0 and set sha1 to the name of the object; * successful, return 0 and set oid to the name of the object;
* otherwise, return a non-zero value. * otherwise, return a non-zero value.
*/ */
int resolve_gitlink_ref(const char *submodule, const char *refname, int resolve_gitlink_ref(const char *submodule, const char *refname,
@ -260,7 +260,7 @@ struct ref_transaction;
/* /*
* The signature for the callback function for the for_each_*() * The signature for the callback function for the for_each_*()
* functions below. The memory pointed to by the refname and sha1 * functions below. The memory pointed to by the refname and oid
* arguments is only guaranteed to be valid for the duration of a * arguments is only guaranteed to be valid for the duration of a
* single callback invocation. * single callback invocation.
*/ */
@ -335,24 +335,6 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt,
*/ */
int refs_pack_refs(struct ref_store *refs, unsigned int flags); int refs_pack_refs(struct ref_store *refs, unsigned int flags);
/*
* Flags controlling ref_transaction_update(), ref_transaction_create(), etc.
* REF_NODEREF: act on the ref directly, instead of dereferencing
* symbolic references.
*
* Other flags are reserved for internal use.
*/
#define REF_NODEREF 0x01
#define REF_FORCE_CREATE_REFLOG 0x40
/*
* Flags that can be passed in to ref_transaction_update
*/
#define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \
REF_ISPRUNING | \
REF_FORCE_CREATE_REFLOG | \
REF_NODEREF
/* /*
* Setup reflog before using. Fill in err and return -1 on failure. * Setup reflog before using. Fill in err and return -1 on failure.
*/ */
@ -372,7 +354,7 @@ int reflog_exists(const char *refname);
/* /*
* Delete the specified reference. If old_oid is non-NULL, then * Delete the specified reference. If old_oid is non-NULL, then
* verify that the current value of the reference is old_sha1 before * verify that the current value of the reference is old_oid before
* deleting it. If old_oid is NULL, delete the reference if it * deleting it. If old_oid is NULL, delete the reference if it
* exists, regardless of its old value. It is an error for old_oid to * exists, regardless of its old value. It is an error for old_oid to
* be null_oid. msg and flags are passed through to * be null_oid. msg and flags are passed through to
@ -480,22 +462,23 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err);
* *
* refname -- the name of the reference to be affected. * refname -- the name of the reference to be affected.
* *
* new_sha1 -- the SHA-1 that should be set to be the new value of * new_oid -- the object ID that should be set to be the new value
* the reference. Some functions allow this parameter to be * of the reference. Some functions allow this parameter to be
* NULL, meaning that the reference is not changed, or * NULL, meaning that the reference is not changed, or
* null_sha1, meaning that the reference should be deleted. A * null_oid, meaning that the reference should be deleted. A
* copy of this value is made in the transaction. * copy of this value is made in the transaction.
* *
* old_sha1 -- the SHA-1 value that the reference must have before * old_oid -- the object ID that the reference must have before
* the update. Some functions allow this parameter to be NULL, * the update. Some functions allow this parameter to be NULL,
* meaning that the old value of the reference is not checked, * meaning that the old value of the reference is not checked,
* or null_sha1, meaning that the reference must not exist * or null_oid, meaning that the reference must not exist
* before the update. A copy of this value is made in the * before the update. A copy of this value is made in the
* transaction. * transaction.
* *
* flags -- flags affecting the update, passed to * flags -- flags affecting the update, passed to
* update_ref_lock(). Can be REF_NODEREF, which means that * update_ref_lock(). Possible flags: REF_NO_DEREF,
* symbolic references should not be followed. * REF_FORCE_CREATE_REFLOG. See those constants for more
* information.
* *
* msg -- a message describing the change (for the reflog). * msg -- a message describing the change (for the reflog).
* *
@ -511,11 +494,37 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err);
*/ */
/* /*
* Add a reference update to transaction. new_oid is the value that * The following flags can be passed to ref_transaction_update() etc.
* the reference should have after the update, or null_oid if it * Internally, they are stored in `ref_update::flags`, along with some
* should be deleted. If new_oid is NULL, then the reference is not * internal flags.
* changed at all. old_oid is the value that the reference must have */
* before the update, or null_oid if it must not have existed
/*
* Act on the ref directly; i.e., without dereferencing symbolic refs.
* If this flag is not specified, then symbolic references are
* dereferenced and the update is applied to the referent.
*/
#define REF_NO_DEREF (1 << 0)
/*
* Force the creation of a reflog for this reference, even if it
* didn't previously have a reflog.
*/
#define REF_FORCE_CREATE_REFLOG (1 << 1)
/*
* Bitmask of all of the flags that are allowed to be passed in to
* ref_transaction_update() and friends:
*/
#define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \
(REF_NO_DEREF | REF_FORCE_CREATE_REFLOG)
/*
* Add a reference update to transaction. `new_oid` is the value that
* the reference should have after the update, or `null_oid` if it
* should be deleted. If `new_oid` is NULL, then the reference is not
* changed at all. `old_oid` is the value that the reference must have
* before the update, or `null_oid` if it must not have existed
* beforehand. The old value is checked after the lock is taken to * beforehand. The old value is checked after the lock is taken to
* prevent races. If the old value doesn't agree with old_oid, the * prevent races. If the old value doesn't agree with old_oid, the
* whole transaction fails. If old_oid is NULL, then the previous * whole transaction fails. If old_oid is NULL, then the previous
@ -624,7 +633,7 @@ int ref_transaction_abort(struct ref_transaction *transaction,
* It is a bug to call this function when there might be other * It is a bug to call this function when there might be other
* processes accessing the repository or if there are existing * processes accessing the repository or if there are existing
* references that might conflict with the ones being created. All * references that might conflict with the ones being created. All
* old_sha1 values must either be absent or NULL_SHA1. * old_oid values must either be absent or null_oid.
*/ */
int initial_ref_transaction_commit(struct ref_transaction *transaction, int initial_ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err); struct strbuf *err);

View File

@ -10,6 +10,51 @@
#include "../object.h" #include "../object.h"
#include "../dir.h" #include "../dir.h"
/*
* This backend uses the following flags in `ref_update::flags` for
* internal bookkeeping purposes. Their numerical values must not
* conflict with REF_NO_DEREF, REF_FORCE_CREATE_REFLOG, REF_HAVE_NEW,
* REF_HAVE_OLD, or REF_IS_PRUNING, which are also stored in
* `ref_update::flags`.
*/
/*
* Used as a flag in ref_update::flags when a loose ref is being
* pruned. This flag must only be used when REF_NO_DEREF is set.
*/
#define REF_IS_PRUNING (1 << 4)
/*
* Flag passed to lock_ref_sha1_basic() telling it to tolerate broken
* refs (i.e., because the reference is about to be deleted anyway).
*/
#define REF_DELETING (1 << 5)
/*
* Used as a flag in ref_update::flags when the lockfile needs to be
* committed.
*/
#define REF_NEEDS_COMMIT (1 << 6)
/*
* Used as a flag in ref_update::flags when we want to log a ref
* update but not actually perform it. This is used when a symbolic
* ref update is split up.
*/
#define REF_LOG_ONLY (1 << 7)
/*
* Used as a flag in ref_update::flags when the ref_update was via an
* update to HEAD.
*/
#define REF_UPDATE_VIA_HEAD (1 << 8)
/*
* Used as a flag in ref_update::flags when the loose reference has
* been deleted.
*/
#define REF_DELETED_LOOSE (1 << 9)
struct ref_lock { struct ref_lock {
char *ref_name; char *ref_name;
struct lock_file lk; struct lock_file lk;
@ -195,7 +240,7 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
} else if (is_null_oid(&oid)) { } else if (is_null_oid(&oid)) {
/* /*
* It is so astronomically unlikely * It is so astronomically unlikely
* that NULL_SHA1 is the SHA-1 of an * that null_oid is the OID of an
* actual object that we consider its * actual object that we consider its
* appearance in a loose reference * appearance in a loose reference
* file to be repo corruption * file to be repo corruption
@ -428,7 +473,7 @@ static void unlock_ref(struct ref_lock *lock)
* are passed to refs_verify_refname_available() for this check. * are passed to refs_verify_refname_available() for this check.
* *
* If mustexist is not set and the reference is not found or is * If mustexist is not set and the reference is not found or is
* broken, lock the reference anyway but clear sha1. * broken, lock the reference anyway but clear old_oid.
* *
* Return 0 on success. On failure, write an error message to err and * Return 0 on success. On failure, write an error message to err and
* return TRANSACTION_NAME_CONFLICT or TRANSACTION_GENERIC_ERROR. * return TRANSACTION_NAME_CONFLICT or TRANSACTION_GENERIC_ERROR.
@ -989,22 +1034,29 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
{ {
struct ref_transaction *transaction; struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT; struct strbuf err = STRBUF_INIT;
int ret = -1;
if (check_refname_format(r->name, 0)) if (check_refname_format(r->name, 0))
return; return;
transaction = ref_store_transaction_begin(&refs->base, &err); transaction = ref_store_transaction_begin(&refs->base, &err);
if (!transaction || if (!transaction)
ref_transaction_delete(transaction, r->name, &r->oid, goto cleanup;
REF_ISPRUNING | REF_NODEREF, NULL, &err) || ref_transaction_add_update(
ref_transaction_commit(transaction, &err)) { transaction, r->name,
ref_transaction_free(transaction); REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,
&null_oid, &r->oid, NULL);
if (ref_transaction_commit(transaction, &err))
goto cleanup;
ret = 0;
cleanup:
if (ret)
error("%s", err.buf); error("%s", err.buf);
strbuf_release(&err);
return;
}
ref_transaction_free(transaction);
strbuf_release(&err); strbuf_release(&err);
ref_transaction_free(transaction);
return;
} }
/* /*
@ -1081,7 +1133,7 @@ static int files_pack_refs(struct ref_store *ref_store, unsigned int flags)
*/ */
if (ref_transaction_update(transaction, iter->refname, if (ref_transaction_update(transaction, iter->refname,
iter->oid, NULL, iter->oid, NULL,
REF_NODEREF, NULL, &err)) REF_NO_DEREF, NULL, &err))
die("failure preparing to create packed reference %s: %s", die("failure preparing to create packed reference %s: %s",
iter->refname, err.buf); iter->refname, err.buf);
@ -1284,7 +1336,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
} }
if (!copy && refs_delete_ref(&refs->base, logmsg, oldrefname, if (!copy && refs_delete_ref(&refs->base, logmsg, oldrefname,
&orig_oid, REF_NODEREF)) { &orig_oid, REF_NO_DEREF)) {
error("unable to delete old %s", oldrefname); error("unable to delete old %s", oldrefname);
goto rollback; goto rollback;
} }
@ -1300,7 +1352,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE, RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
&oid, NULL) && &oid, NULL) &&
refs_delete_ref(&refs->base, NULL, newrefname, refs_delete_ref(&refs->base, NULL, newrefname,
NULL, REF_NODEREF)) { NULL, REF_NO_DEREF)) {
if (errno == EISDIR) { if (errno == EISDIR) {
struct strbuf path = STRBUF_INIT; struct strbuf path = STRBUF_INIT;
int result; int result;
@ -1325,7 +1377,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
logmoved = log; logmoved = log;
lock = lock_ref_oid_basic(refs, newrefname, NULL, NULL, NULL, lock = lock_ref_oid_basic(refs, newrefname, NULL, NULL, NULL,
REF_NODEREF, NULL, &err); REF_NO_DEREF, NULL, &err);
if (!lock) { if (!lock) {
if (copy) if (copy)
error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf); error("unable to copy '%s' to '%s': %s", oldrefname, newrefname, err.buf);
@ -1348,7 +1400,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,
rollback: rollback:
lock = lock_ref_oid_basic(refs, oldrefname, NULL, NULL, NULL, lock = lock_ref_oid_basic(refs, oldrefname, NULL, NULL, NULL,
REF_NODEREF, NULL, &err); REF_NO_DEREF, NULL, &err);
if (!lock) { if (!lock) {
error("unable to lock %s for rollback: %s", oldrefname, err.buf); error("unable to lock %s for rollback: %s", oldrefname, err.buf);
strbuf_release(&err); strbuf_release(&err);
@ -1596,9 +1648,8 @@ static int files_log_ref_write(struct files_ref_store *refs,
} }
/* /*
* Write sha1 into the open lockfile, then close the lockfile. On * Write oid into the open lockfile, then close the lockfile. On
* errors, rollback the lockfile, fill in *err and * errors, rollback the lockfile, fill in *err and return -1.
* return -1.
*/ */
static int write_ref_to_lockfile(struct ref_lock *lock, static int write_ref_to_lockfile(struct ref_lock *lock,
const struct object_id *oid, struct strbuf *err) const struct object_id *oid, struct strbuf *err)
@ -1764,7 +1815,7 @@ static int files_create_symref(struct ref_store *ref_store,
int ret; int ret;
lock = lock_ref_oid_basic(refs, refname, NULL, lock = lock_ref_oid_basic(refs, refname, NULL,
NULL, NULL, REF_NODEREF, NULL, NULL, NULL, REF_NO_DEREF, NULL,
&err); &err);
if (!lock) { if (!lock) {
error("%s", err.buf); error("%s", err.buf);
@ -2125,7 +2176,7 @@ static int split_head_update(struct ref_update *update,
struct ref_update *new_update; struct ref_update *new_update;
if ((update->flags & REF_LOG_ONLY) || if ((update->flags & REF_LOG_ONLY) ||
(update->flags & REF_ISPRUNING) || (update->flags & REF_IS_PRUNING) ||
(update->flags & REF_UPDATE_VIA_HEAD)) (update->flags & REF_UPDATE_VIA_HEAD))
return 0; return 0;
@ -2148,7 +2199,7 @@ static int split_head_update(struct ref_update *update,
new_update = ref_transaction_add_update( new_update = ref_transaction_add_update(
transaction, "HEAD", transaction, "HEAD",
update->flags | REF_LOG_ONLY | REF_NODEREF, update->flags | REF_LOG_ONLY | REF_NO_DEREF,
&update->new_oid, &update->old_oid, &update->new_oid, &update->old_oid,
update->msg); update->msg);
@ -2167,8 +2218,8 @@ static int split_head_update(struct ref_update *update,
/* /*
* update is for a symref that points at referent and doesn't have * update is for a symref that points at referent and doesn't have
* REF_NODEREF set. Split it into two updates: * REF_NO_DEREF set. Split it into two updates:
* - The original update, but with REF_LOG_ONLY and REF_NODEREF set * - The original update, but with REF_LOG_ONLY and REF_NO_DEREF set
* - A new, separate update for the referent reference * - A new, separate update for the referent reference
* Note that the new update will itself be subject to splitting when * Note that the new update will itself be subject to splitting when
* the iteration gets to it. * the iteration gets to it.
@ -2220,10 +2271,10 @@ static int split_symref_update(struct files_ref_store *refs,
/* /*
* Change the symbolic ref update to log only. Also, it * Change the symbolic ref update to log only. Also, it
* doesn't need to check its old SHA-1 value, as that will be * doesn't need to check its old OID value, as that will be
* done when new_update is processed. * done when new_update is processed.
*/ */
update->flags |= REF_LOG_ONLY | REF_NODEREF; update->flags |= REF_LOG_ONLY | REF_NO_DEREF;
update->flags &= ~REF_HAVE_OLD; update->flags &= ~REF_HAVE_OLD;
/* /*
@ -2289,10 +2340,10 @@ static int check_old_oid(struct ref_update *update, struct object_id *oid,
* Prepare for carrying out update: * Prepare for carrying out update:
* - Lock the reference referred to by update. * - Lock the reference referred to by update.
* - Read the reference under lock. * - Read the reference under lock.
* - Check that its old SHA-1 value (if specified) is correct, and in * - Check that its old OID value (if specified) is correct, and in
* any case record it in update->lock->old_oid for later use when * any case record it in update->lock->old_oid for later use when
* writing the reflog. * writing the reflog.
* - If it is a symref update without REF_NODEREF, split it up into a * - If it is a symref update without REF_NO_DEREF, split it up into a
* REF_LOG_ONLY update of the symref and add a separate update for * REF_LOG_ONLY update of the symref and add a separate update for
* the referent to transaction. * the referent to transaction.
* - If it is an update of head_ref, add a corresponding REF_LOG_ONLY * - If it is an update of head_ref, add a corresponding REF_LOG_ONLY
@ -2340,11 +2391,11 @@ static int lock_ref_for_update(struct files_ref_store *refs,
update->backend_data = lock; update->backend_data = lock;
if (update->type & REF_ISSYMREF) { if (update->type & REF_ISSYMREF) {
if (update->flags & REF_NODEREF) { if (update->flags & REF_NO_DEREF) {
/* /*
* We won't be reading the referent as part of * We won't be reading the referent as part of
* the transaction, so we have to read it here * the transaction, so we have to read it here
* to record and possibly check old_sha1: * to record and possibly check old_oid:
*/ */
if (refs_read_ref_full(&refs->base, if (refs_read_ref_full(&refs->base,
referent.buf, 0, referent.buf, 0,
@ -2364,7 +2415,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
/* /*
* Create a new update for the reference this * Create a new update for the reference this
* symref is pointing at. Also, we will record * symref is pointing at. Also, we will record
* and verify old_sha1 for this update as part * and verify old_oid for this update as part
* of processing the split-off update, so we * of processing the split-off update, so we
* don't have to do it here. * don't have to do it here.
*/ */
@ -2384,7 +2435,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
/* /*
* If this update is happening indirectly because of a * If this update is happening indirectly because of a
* symref update, record the old SHA-1 in the parent * symref update, record the old OID in the parent
* update: * update:
*/ */
for (parent_update = update->parent_update; for (parent_update = update->parent_update;
@ -2511,13 +2562,18 @@ static int files_transaction_prepare(struct ref_store *ref_store,
* transaction. (If we end up splitting up any updates using * transaction. (If we end up splitting up any updates using
* split_symref_update() or split_head_update(), those * split_symref_update() or split_head_update(), those
* functions will check that the new updates don't have the * functions will check that the new updates don't have the
* same refname as any existing ones.) * same refname as any existing ones.) Also fail if any of the
* updates use REF_IS_PRUNING without REF_NO_DEREF.
*/ */
for (i = 0; i < transaction->nr; i++) { for (i = 0; i < transaction->nr; i++) {
struct ref_update *update = transaction->updates[i]; struct ref_update *update = transaction->updates[i];
struct string_list_item *item = struct string_list_item *item =
string_list_append(&affected_refnames, update->refname); string_list_append(&affected_refnames, update->refname);
if ((update->flags & REF_IS_PRUNING) &&
!(update->flags & REF_NO_DEREF))
BUG("REF_IS_PRUNING set without REF_NO_DEREF");
/* /*
* We store a pointer to update in item->util, but at * We store a pointer to update in item->util, but at
* the moment we never use the value of this field * the moment we never use the value of this field
@ -2575,7 +2631,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
if (update->flags & REF_DELETING && if (update->flags & REF_DELETING &&
!(update->flags & REF_LOG_ONLY) && !(update->flags & REF_LOG_ONLY) &&
!(update->flags & REF_ISPRUNING)) { !(update->flags & REF_IS_PRUNING)) {
/* /*
* This reference has to be deleted from * This reference has to be deleted from
* packed-refs if it exists there. * packed-refs if it exists there.
@ -2594,8 +2650,8 @@ static int files_transaction_prepare(struct ref_store *ref_store,
ref_transaction_add_update( ref_transaction_add_update(
packed_transaction, update->refname, packed_transaction, update->refname,
update->flags & ~REF_HAVE_OLD, REF_HAVE_NEW | REF_NO_DEREF,
&update->new_oid, &update->old_oid, &update->new_oid, NULL,
NULL); NULL);
} }
} }
@ -2708,7 +2764,7 @@ static int files_transaction_finish(struct ref_store *ref_store,
struct ref_update *update = transaction->updates[i]; struct ref_update *update = transaction->updates[i];
if (update->flags & REF_DELETING && if (update->flags & REF_DELETING &&
!(update->flags & REF_LOG_ONLY) && !(update->flags & REF_LOG_ONLY) &&
!(update->flags & REF_ISPRUNING)) { !(update->flags & REF_IS_PRUNING)) {
strbuf_reset(&sb); strbuf_reset(&sb);
files_reflog_path(refs, &sb, update->refname); files_reflog_path(refs, &sb, update->refname);
if (!unlink_or_warn(sb.buf)) if (!unlink_or_warn(sb.buf))
@ -2954,7 +3010,7 @@ static int files_reflog_expire(struct ref_store *ref_store,
* reference if --updateref was specified: * reference if --updateref was specified:
*/ */
lock = lock_ref_oid_basic(refs, refname, oid, lock = lock_ref_oid_basic(refs, refname, oid,
NULL, NULL, REF_NODEREF, NULL, NULL, REF_NO_DEREF,
&type, &err); &type, &err);
if (!lock) { if (!lock) {
error("cannot lock ref '%s': %s", refname, err.buf); error("cannot lock ref '%s': %s", refname, err.buf);

View File

@ -744,7 +744,7 @@ static int packed_read_raw_ref(struct ref_store *ref_store,
/* /*
* This value is set in `base.flags` if the peeled value of the * This value is set in `base.flags` if the peeled value of the
* current reference is known. In that case, `peeled` contains the * current reference is known. In that case, `peeled` contains the
* correct peeled value for the reference, which might be `null_sha1` * correct peeled value for the reference, which might be `null_oid`
* if the reference is not a tag or if it is broken. * if the reference is not a tag or if it is broken.
*/ */
#define REF_KNOWS_PEELED 0x40 #define REF_KNOWS_PEELED 0x40
@ -961,11 +961,11 @@ static struct ref_iterator *packed_ref_iterator_begin(
* by the failing call to `fprintf()`. * by the failing call to `fprintf()`.
*/ */
static int write_packed_entry(FILE *fh, const char *refname, static int write_packed_entry(FILE *fh, const char *refname,
const unsigned char *sha1, const struct object_id *oid,
const unsigned char *peeled) const struct object_id *peeled)
{ {
if (fprintf(fh, "%s %s\n", sha1_to_hex(sha1), refname) < 0 || if (fprintf(fh, "%s %s\n", oid_to_hex(oid), refname) < 0 ||
(peeled && fprintf(fh, "^%s\n", sha1_to_hex(peeled)) < 0)) (peeled && fprintf(fh, "^%s\n", oid_to_hex(peeled)) < 0))
return -1; return -1;
return 0; return 0;
@ -1203,8 +1203,8 @@ static int write_with_updates(struct packed_ref_store *refs,
int peel_error = ref_iterator_peel(iter, &peeled); int peel_error = ref_iterator_peel(iter, &peeled);
if (write_packed_entry(out, iter->refname, if (write_packed_entry(out, iter->refname,
iter->oid->hash, iter->oid,
peel_error ? NULL : peeled.hash)) peel_error ? NULL : &peeled))
goto write_error; goto write_error;
if ((ok = ref_iterator_advance(iter)) != ITER_OK) if ((ok = ref_iterator_advance(iter)) != ITER_OK)
@ -1224,8 +1224,8 @@ static int write_with_updates(struct packed_ref_store *refs,
&peeled); &peeled);
if (write_packed_entry(out, update->refname, if (write_packed_entry(out, update->refname,
update->new_oid.hash, &update->new_oid,
peel_error ? NULL : peeled.hash)) peel_error ? NULL : &peeled))
goto write_error; goto write_error;
i++; i++;

View File

@ -260,8 +260,8 @@ int add_ref_entry(struct ref_dir *dir, struct ref_entry *ref)
/* /*
* Emit a warning and return true iff ref1 and ref2 have the same name * Emit a warning and return true iff ref1 and ref2 have the same name
* and the same sha1. Die if they have the same name but different * and the same oid. Die if they have the same name but different
* sha1s. * oids.
*/ */
static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2) static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2)
{ {

View File

@ -8,58 +8,22 @@
*/ */
/* /*
* Flag passed to lock_ref_sha1_basic() telling it to tolerate broken * The following flags can appear in `ref_update::flags`. Their
* refs (i.e., because the reference is about to be deleted anyway). * numerical values must not conflict with those of REF_NO_DEREF and
*/ * REF_FORCE_CREATE_REFLOG, which are also stored in
#define REF_DELETING 0x02 * `ref_update::flags`.
/*
* Used as a flag in ref_update::flags when a loose ref is being
* pruned. This flag must only be used when REF_NODEREF is set.
*/
#define REF_ISPRUNING 0x04
/*
* Used as a flag in ref_update::flags when the reference should be
* updated to new_sha1.
*/
#define REF_HAVE_NEW 0x08
/*
* Used as a flag in ref_update::flags when old_sha1 should be
* checked.
*/
#define REF_HAVE_OLD 0x10
/*
* Used as a flag in ref_update::flags when the lockfile needs to be
* committed.
*/
#define REF_NEEDS_COMMIT 0x20
/*
* 0x40 is REF_FORCE_CREATE_REFLOG, so skip it if you're adding a
* value to ref_update::flags
*/ */
/* /*
* Used as a flag in ref_update::flags when we want to log a ref * The reference should be updated to new_oid.
* update but not actually perform it. This is used when a symbolic
* ref update is split up.
*/ */
#define REF_LOG_ONLY 0x80 #define REF_HAVE_NEW (1 << 2)
/* /*
* Internal flag, meaning that the containing ref_update was via an * The current reference's value should be checked to make sure that
* update to HEAD. * it agrees with old_oid.
*/ */
#define REF_UPDATE_VIA_HEAD 0x100 #define REF_HAVE_OLD (1 << 3)
/*
* Used as a flag in ref_update::flags when the loose reference has
* been deleted.
*/
#define REF_DELETED_LOOSE 0x200
/* /*
* Return the length of time to retry acquiring a loose reference lock * Return the length of time to retry acquiring a loose reference lock
@ -122,7 +86,7 @@ enum peel_status {
* tag recursively until a non-tag is found. If successful, store the * tag recursively until a non-tag is found. If successful, store the
* result to oid and return PEEL_PEELED. If the object is not a tag * result to oid and return PEEL_PEELED. If the object is not a tag
* or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively, * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
* and leave sha1 unchanged. * and leave oid unchanged.
*/ */
enum peel_status peel_object(const struct object_id *name, struct object_id *oid); enum peel_status peel_object(const struct object_id *name, struct object_id *oid);
@ -134,30 +98,29 @@ enum peel_status peel_object(const struct object_id *name, struct object_id *oid
int copy_reflog_msg(char *buf, const char *msg); int copy_reflog_msg(char *buf, const char *msg);
/** /**
* Information needed for a single ref update. Set new_sha1 to the new * Information needed for a single ref update. Set new_oid to the new
* value or to null_sha1 to delete the ref. To check the old value * value or to null_oid to delete the ref. To check the old value
* while the ref is locked, set (flags & REF_HAVE_OLD) and set * while the ref is locked, set (flags & REF_HAVE_OLD) and set old_oid
* old_sha1 to the old value, or to null_sha1 to ensure the ref does * to the old value, or to null_oid to ensure the ref does not exist
* not exist before update. * before update.
*/ */
struct ref_update { struct ref_update {
/* /*
* If (flags & REF_HAVE_NEW), set the reference to this value: * If (flags & REF_HAVE_NEW), set the reference to this value
* (or delete it, if `new_oid` is `null_oid`).
*/ */
struct object_id new_oid; struct object_id new_oid;
/* /*
* If (flags & REF_HAVE_OLD), check that the reference * If (flags & REF_HAVE_OLD), check that the reference
* previously had this value: * previously had this value (or didn't previously exist, if
* `old_oid` is `null_oid`).
*/ */
struct object_id old_oid; struct object_id old_oid;
/* /*
* One or more of REF_HAVE_NEW, REF_HAVE_OLD, REF_NODEREF, * One or more of REF_NO_DEREF, REF_FORCE_CREATE_REFLOG,
* REF_DELETING, REF_ISPRUNING, REF_LOG_ONLY, * REF_HAVE_NEW, REF_HAVE_OLD, or backend-specific flags.
* REF_UPDATE_VIA_HEAD, REF_NEEDS_COMMIT, and
* REF_DELETED_LOOSE:
*/ */
unsigned int flags; unsigned int flags;
@ -195,7 +158,7 @@ int ref_update_reject_duplicates(struct string_list *refnames,
/* /*
* Add a ref_update with the specified properties to transaction, and * Add a ref_update with the specified properties to transaction, and
* return a pointer to the new object. This function does not verify * return a pointer to the new object. This function does not verify
* that refname is well-formed. new_sha1 and old_sha1 are only * that refname is well-formed. new_oid and old_oid are only
* dereferenced if the REF_HAVE_NEW and REF_HAVE_OLD bits, * dereferenced if the REF_HAVE_NEW and REF_HAVE_OLD bits,
* respectively, are set in flags. * respectively, are set in flags.
*/ */

View File

@ -1117,11 +1117,11 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
*/ */
if (command == TODO_PICK && !opts->no_commit && (res == 0 || res == 1) && if (command == TODO_PICK && !opts->no_commit && (res == 0 || res == 1) &&
update_ref(NULL, "CHERRY_PICK_HEAD", &commit->object.oid, NULL, update_ref(NULL, "CHERRY_PICK_HEAD", &commit->object.oid, NULL,
REF_NODEREF, UPDATE_REFS_MSG_ON_ERR)) REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
res = -1; res = -1;
if (command == TODO_REVERT && ((opts->no_commit && res == 0) || res == 1) && if (command == TODO_REVERT && ((opts->no_commit && res == 0) || res == 1) &&
update_ref(NULL, "REVERT_HEAD", &commit->object.oid, NULL, update_ref(NULL, "REVERT_HEAD", &commit->object.oid, NULL,
REF_NODEREF, UPDATE_REFS_MSG_ON_ERR)) REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
res = -1; res = -1;
if (res) { if (res) {
@ -2130,7 +2130,7 @@ cleanup_head_ref:
msg = reflog_message(opts, "finish", "%s onto %s", msg = reflog_message(opts, "finish", "%s onto %s",
head_ref.buf, buf.buf); head_ref.buf, buf.buf);
if (update_ref(msg, head_ref.buf, &head, &orig, if (update_ref(msg, head_ref.buf, &head, &orig,
REF_NODEREF, UPDATE_REFS_MSG_ON_ERR)) { REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) {
res = error(_("could not update %s"), res = error(_("could not update %s"),
head_ref.buf); head_ref.buf);
goto cleanup_head_ref; goto cleanup_head_ref;