aboutsummaryrefslogtreecommitdiffstats
path: root/refs.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2024-06-20 15:45:11 -0700
committerJunio C Hamano <gitster@pobox.com>2024-06-20 15:45:12 -0700
commit5f14d2098478cc96251b52d812c5a3ebc3e03a42 (patch)
tree6d2e5ad5e0c0649cb863490ca5c73e4c1e076043 /refs.c
parentc1322ca47457a1e866845cdd69a4f848bf71a5c5 (diff)
parent7dd4051b014741732271785c0915599b1f0c1a47 (diff)
downloadgit-5f14d2098478cc96251b52d812c5a3ebc3e03a42.tar.gz
Merge branch 'kn/update-ref-symref'
"git update-ref --stdin" learned to handle transactional updates of symbolic-refs. * kn/update-ref-symref: update-ref: add support for 'symref-update' command reftable: pick either 'oid' or 'target' for new updates update-ref: add support for 'symref-create' command update-ref: add support for 'symref-delete' command update-ref: add support for 'symref-verify' command refs: specify error for regular refs with `old_target` refs: create and use `ref_update_expects_existing_old_ref()`
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/refs.c b/refs.c
index 0c1e45f5a9..dd0d9c360f 100644
--- a/refs.c
+++ b/refs.c
@@ -914,7 +914,7 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
transaction = ref_store_transaction_begin(refs, &err);
if (!transaction ||
ref_transaction_delete(transaction, refname, old_oid,
- flags, msg, &err) ||
+ NULL, flags, msg, &err) ||
ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
ref_transaction_free(transaction);
@@ -1238,43 +1238,57 @@ int ref_transaction_update(struct ref_transaction *transaction,
int ref_transaction_create(struct ref_transaction *transaction,
const char *refname,
const struct object_id *new_oid,
+ const char *new_target,
unsigned int flags, const char *msg,
struct strbuf *err)
{
- if (!new_oid || is_null_oid(new_oid)) {
- strbuf_addf(err, "'%s' has a null OID", refname);
+ if (new_oid && new_target)
+ BUG("create called with both new_oid and new_target set");
+ if ((!new_oid || is_null_oid(new_oid)) && !new_target) {
+ strbuf_addf(err, "'%s' has neither a valid OID nor a target", refname);
return 1;
}
return ref_transaction_update(transaction, refname, new_oid,
- null_oid(), NULL, NULL, flags,
+ null_oid(), new_target, NULL, flags,
msg, err);
}
int ref_transaction_delete(struct ref_transaction *transaction,
const char *refname,
const struct object_id *old_oid,
- unsigned int flags, const char *msg,
+ const char *old_target,
+ unsigned int flags,
+ const char *msg,
struct strbuf *err)
{
if (old_oid && is_null_oid(old_oid))
BUG("delete called with old_oid set to zeros");
+ if (old_oid && old_target)
+ BUG("delete called with both old_oid and old_target set");
+ if (old_target && !(flags & REF_NO_DEREF))
+ BUG("delete cannot operate on symrefs with deref mode");
return ref_transaction_update(transaction, refname,
null_oid(), old_oid,
- NULL, NULL, flags,
+ NULL, old_target, flags,
msg, err);
}
int ref_transaction_verify(struct ref_transaction *transaction,
const char *refname,
const struct object_id *old_oid,
+ const char *old_target,
unsigned int flags,
struct strbuf *err)
{
- if (!old_oid)
- BUG("verify called with old_oid set to NULL");
+ if (!old_target && !old_oid)
+ BUG("verify called with old_oid and old_target set to NULL");
+ if (old_oid && old_target)
+ BUG("verify called with both old_oid and old_target set");
+ if (old_target && !(flags & REF_NO_DEREF))
+ BUG("verify cannot operate on symrefs with deref mode");
return ref_transaction_update(transaction, refname,
NULL, old_oid,
- NULL, NULL,
+ NULL, old_target,
flags, NULL, err);
}
@@ -2485,7 +2499,7 @@ int refs_delete_refs(struct ref_store *refs, const char *logmsg,
for_each_string_list_item(item, refnames) {
ret = ref_transaction_delete(transaction, item->string,
- NULL, flags, msg, &err);
+ NULL, NULL, flags, msg, &err);
if (ret) {
warning(_("could not delete reference %s: %s"),
item->string, err.buf);
@@ -2595,7 +2609,7 @@ static int migrate_one_ref(const char *refname, const struct object_id *oid,
if (ret < 0)
goto done;
} else {
- ret = ref_transaction_create(data->transaction, refname, oid,
+ ret = ref_transaction_create(data->transaction, refname, oid, NULL,
REF_SKIP_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION,
NULL, data->errbuf);
if (ret < 0)
@@ -2878,3 +2892,10 @@ done:
strbuf_release(&new_gitdir);
return ret;
}
+
+int ref_update_expects_existing_old_ref(struct ref_update *update)
+{
+ return (update->flags & REF_HAVE_OLD) &&
+ (!is_null_oid(&update->old_oid) || update->old_target);
+}
+