diff options
| author | Junio C Hamano <gitster@pobox.com> | 2024-12-19 10:58:27 -0800 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2024-12-19 10:58:27 -0800 |
| commit | 5f212684abb66c9604e745a2296af8c4bb99961c (patch) | |
| tree | 16d25571b9d3d66c5ccf49df359c7adb99a0124c /refs.c | |
| parent | Merge https://github.com/j6t/gitk (diff) | |
| parent | fetch set_head: handle mirrored bare repositories (diff) | |
| download | git-5f212684abb66c9604e745a2296af8c4bb99961c.tar.gz git-5f212684abb66c9604e745a2296af8c4bb99961c.zip | |
Merge branch 'bf/set-head-symref'
When "git fetch $remote" notices that refs/remotes/$remote/HEAD is
missing and discovers what branch the other side points with its
HEAD, refs/remotes/$remote/HEAD is updated to point to it.
* bf/set-head-symref:
fetch set_head: handle mirrored bare repositories
fetch: set remote/HEAD if it does not exist
refs: add create_only option to refs_update_symref_extended
refs: add TRANSACTION_CREATE_EXISTS error
remote set-head: better output for --auto
remote set-head: refactor for readability
refs: atomically record overwritten ref in update_symref
refs: standardize output of refs_read_symbolic_ref
t/t5505-remote: test failure of set-head
t/t5505-remote: set default branch to main
Diffstat (limited to 'refs.c')
| -rw-r--r-- | refs.c | 47 |
1 files changed, 40 insertions, 7 deletions
@@ -2167,19 +2167,53 @@ int peel_iterated_oid(struct repository *r, const struct object_id *base, struct int refs_update_symref(struct ref_store *refs, const char *ref, const char *target, const char *logmsg) { + return refs_update_symref_extended(refs, ref, target, logmsg, NULL, 0); +} + +int refs_update_symref_extended(struct ref_store *refs, const char *ref, + const char *target, const char *logmsg, + struct strbuf *referent, int create_only) +{ struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; - int ret = 0; + int ret = 0, prepret = 0; transaction = ref_store_transaction_begin(refs, 0, &err); - if (!transaction || - ref_transaction_update(transaction, ref, NULL, NULL, - target, NULL, REF_NO_DEREF, - logmsg, &err) || - ref_transaction_commit(transaction, &err)) { + if (!transaction) { + error_return: ret = error("%s", err.buf); + goto cleanup; + } + if (create_only) { + if (ref_transaction_create(transaction, ref, NULL, target, + REF_NO_DEREF, logmsg, &err)) + goto error_return; + prepret = ref_transaction_prepare(transaction, &err); + if (prepret && prepret != TRANSACTION_CREATE_EXISTS) + goto error_return; + } else { + if (ref_transaction_update(transaction, ref, NULL, NULL, + target, NULL, REF_NO_DEREF, + logmsg, &err) || + ref_transaction_prepare(transaction, &err)) + goto error_return; + } + + if (referent && refs_read_symbolic_ref(refs, ref, referent) == NOT_A_SYMREF) { + struct object_id oid; + if (!refs_read_ref(refs, ref, &oid)) { + strbuf_addstr(referent, oid_to_hex(&oid)); + ret = NOT_A_SYMREF; + } } + if (prepret == TRANSACTION_CREATE_EXISTS) + goto cleanup; + + if (ref_transaction_commit(transaction, &err)) + goto error_return; + +cleanup: strbuf_release(&err); if (transaction) ref_transaction_free(transaction); @@ -2993,4 +3027,3 @@ 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); } - |
