From: Junio C Hamano Date: Thu, 19 Dec 2024 18:58:27 +0000 (-0800) Subject: Merge branch 'bf/set-head-symref' X-Git-Tag: v2.48.0-rc1~30 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5f212684abb66c9604e745a2296af8c4bb99961c;p=thirdparty%2Fgit.git 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 --- 5f212684abb66c9604e745a2296af8c4bb99961c diff --cc builtin/remote.c index 1ad3e70a6b,3dc1135b5c..d5b81445f2 --- a/builtin/remote.c +++ b/builtin/remote.c @@@ -1403,12 -1399,40 +1403,41 @@@ static int show(int argc, const char ** return result; } + static void report_set_head_auto(const char *remote, const char *head_name, + struct strbuf *b_local_head, int was_detached) { + struct strbuf buf_prefix = STRBUF_INIT; + const char *prev_head = NULL; + + strbuf_addf(&buf_prefix, "refs/remotes/%s/", remote); + skip_prefix(b_local_head->buf, buf_prefix.buf, &prev_head); + + if (prev_head && !strcmp(prev_head, head_name)) + printf(_("'%s/HEAD' is unchanged and points to '%s'\n"), + remote, head_name); + else if (prev_head) + printf(_("'%s/HEAD' has changed from '%s' and now points to '%s'\n"), + remote, prev_head, head_name); + else if (!b_local_head->len) + printf(_("'%s/HEAD' is now created and points to '%s'\n"), + remote, head_name); + else if (was_detached && b_local_head->len) + printf(_("'%s/HEAD' was detached at '%s' and now points to '%s'\n"), + remote, b_local_head->buf, head_name); + else + printf(_("'%s/HEAD' used to point to '%s' " + "(which is not a remote branch), but now points to '%s'\n"), + remote, b_local_head->buf, head_name); + strbuf_release(&buf_prefix); + } + -static int set_head(int argc, const char **argv, const char *prefix) +static int set_head(int argc, const char **argv, const char *prefix, + struct repository *repo UNUSED) { - int i, opt_a = 0, opt_d = 0, result = 0; - struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT; + int i, opt_a = 0, opt_d = 0, result = 0, was_detached; + struct strbuf b_head = STRBUF_INIT, b_remote_head = STRBUF_INIT, + b_local_head = STRBUF_INIT; char *head_name = NULL; + struct ref_store *refs = get_main_ref_store(the_repository); struct option options[] = { OPT_BOOL('a', "auto", &opt_a, diff --cc refs.c index 8b71369235,2efa6bcc5c..bc0a60c186 --- a/refs.c +++ b/refs.c @@@ -2169,17 -2125,44 +2176,44 @@@ int refs_update_symref_extended(struct { struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; - int ret = 0; + int ret = 0, prepret = 0; - transaction = ref_store_transaction_begin(refs, &err); + 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); diff --cc refs/reftable-backend.c index 31c58db29f,d764c2c3af..8a2a5b847c --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@@ -919,9 -829,15 +919,13 @@@ static int reftable_be_read_symbolic_re if (ret) return ret; - ret = reftable_stack_read_ref(stack, refname, &ref); + ret = reftable_backend_read_ref(be, refname, &oid, referent, &type); - if (type != REF_ISSYMREF) + if (ret) ret = -1; - else if (ref.value_type == REFTABLE_REF_SYMREF) - strbuf_addstr(referent, ref.value.symref); ++ else if (type == REF_ISSYMREF) ++ ; /* happy */ + else + ret = NOT_A_SYMREF; - - reftable_ref_record_release(&ref); return ret; } diff --cc t/t5505-remote.sh index 08424e878e,2600add82a..7411aa770d --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@@ -2,6 -2,10 +2,9 @@@ test_description='git remote porcelain-ish' + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main + export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + -TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh setup_repository () {