]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'bf/set-head-symref'
authorJunio C Hamano <gitster@pobox.com>
Thu, 19 Dec 2024 18:58:27 +0000 (10:58 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 19 Dec 2024 18:58:27 +0000 (10:58 -0800)
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

16 files changed:
1  2 
builtin/fetch.c
builtin/remote.c
refs.c
refs.h
refs/files-backend.c
refs/refs-internal.h
refs/reftable-backend.c
t/t4207-log-decoration-colors.sh
t/t5505-remote.sh
t/t5510-fetch.sh
t/t5512-ls-remote.sh
t/t5514-fetch-multiple.sh
t/t5516-fetch-push.sh
t/t5527-fetch-odd-refs.sh
t/t7900-maintenance.sh
t/t9902-completion.sh

diff --cc builtin/fetch.c
Simple merge
index 1ad3e70a6b438a3c4446b16c02dc5c23c7fa14be,3dc1135b5cef44a19b4ee99309cd472fc4a76415..d5b81445f2d12ccfb5e6c6656f51cc496a52f8c8
@@@ -1403,12 -1399,40 +1403,41 @@@ static int show(int argc, const char **
        return result;
  }
  
 -static int set_head(int argc, const char **argv, const char *prefix)
+ 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,
 +                  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 8b713692359a640e883c3f36e85f929b04cdae31,2efa6bcc5c802bbcdf96afecfaf50a70a4b520c4..bc0a60c186aca529511067738ecd21f06177f8ec
--- 1/refs.c
--- 2/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.h
Simple merge
Simple merge
Simple merge
index 31c58db29ff6c124a8f17f97ed8edae3a6ee91f0,d764c2c3afaadedc201c16ab80d24d3e14dfd1c2..8a2a5b847c3d86332e319da69bfb5c8a56a10e86
@@@ -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;
  }
  
Simple merge
index 08424e878e104cc19a43960b987cf868f542cad2,2600add82a7cb0e0434ef7a0a65d747639c5d6da..7411aa770d3564489ad3e01a515623787535daa8
@@@ -2,6 -2,10 +2,9 @@@
  
  test_description='git remote porcelain-ish'
  
 -TEST_PASSES_SANITIZE_LEAK=true
+ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
  . ./test-lib.sh
  
  setup_repository () {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge