diff options
| author | Junio C Hamano <gitster@pobox.com> | 2024-06-20 15:45:11 -0700 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2024-06-20 15:45:12 -0700 |
| commit | 5f14d2098478cc96251b52d812c5a3ebc3e03a42 (patch) | |
| tree | 6d2e5ad5e0c0649cb863490ca5c73e4c1e076043 /refs | |
| parent | c1322ca47457a1e866845cdd69a4f848bf71a5c5 (diff) | |
| parent | 7dd4051b014741732271785c0915599b1f0c1a47 (diff) | |
| download | git-5f14d2098478cc96251b52d812c5a3ebc3e03a42.tar.xz | |
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')
| -rw-r--r-- | refs/files-backend.c | 17 | ||||
| -rw-r--r-- | refs/refs-internal.h | 6 | ||||
| -rw-r--r-- | refs/reftable-backend.c | 17 |
3 files changed, 29 insertions, 11 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c index 4519b46171..44c5c3b201 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -2457,8 +2457,7 @@ static int lock_ref_for_update(struct files_ref_store *refs, struct strbuf *err) { struct strbuf referent = STRBUF_INIT; - int mustexist = (update->flags & REF_HAVE_OLD) && - !is_null_oid(&update->old_oid); + int mustexist = ref_update_expects_existing_old_ref(update); int ret = 0; struct ref_lock *lock; @@ -2537,14 +2536,16 @@ static int lock_ref_for_update(struct files_ref_store *refs, /* * Even if the ref is a regular ref, if `old_target` is set, we - * check the referent value. Ideally `old_target` should only - * be set for symrefs, but we're strict about its usage. + * fail with an error. */ if (update->old_target) { - if (ref_update_check_old_target(referent.buf, update, err)) { - ret = TRANSACTION_GENERIC_ERROR; - goto out; - } + strbuf_addf(err, _("cannot lock ref '%s': " + "expected symref with target '%s': " + "but is a regular ref"), + ref_update_original_update_refname(update), + update->old_target); + ret = TRANSACTION_GENERIC_ERROR; + goto out; } else if (check_old_oid(update, &lock->old_oid, err)) { ret = TRANSACTION_GENERIC_ERROR; goto out; diff --git a/refs/refs-internal.h b/refs/refs-internal.h index cbcb6f9c36..fa975d69aa 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -742,4 +742,10 @@ int ref_update_has_null_new_value(struct ref_update *update); int ref_update_check_old_target(const char *referent, struct ref_update *update, struct strbuf *err); +/* + * Check if the ref must exist, this means that the old_oid or + * old_target is non NULL. + */ +int ref_update_expects_existing_old_ref(struct ref_update *update); + #endif /* REFS_REFS_INTERNAL_H */ diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index 3a75d63eb5..7d872a32ac 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -934,7 +934,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, ¤t_oid, &referent, &u->type); if (ret < 0) goto done; - if (ret > 0 && (!(u->flags & REF_HAVE_OLD) || is_null_oid(&u->old_oid))) { + if (ret > 0 && !ref_update_expects_existing_old_ref(u)) { /* * The reference does not exist, and we either have no * old object ID or expect the reference to not exist. @@ -1005,8 +1005,9 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, */ new_update = ref_transaction_add_update( transaction, referent.buf, new_flags, - &u->new_oid, &u->old_oid, u->new_target, - u->old_target, u->msg); + u->new_target ? NULL : &u->new_oid, + u->old_target ? NULL : &u->old_oid, + u->new_target, u->old_target, u->msg); new_update->parent_update = u; @@ -1038,6 +1039,16 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store, * backend returns, which keeps our tests happy. */ if (u->old_target) { + if (!(u->type & REF_ISSYMREF)) { + strbuf_addf(err, _("cannot lock ref '%s': " + "expected symref with target '%s': " + "but is a regular ref"), + ref_update_original_update_refname(u), + u->old_target); + ret = -1; + goto done; + } + if (ref_update_check_old_target(referent.buf, u, err)) { ret = -1; goto done; |
