git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Felipe Contreras <felipe.contreras@gmail.com>
To: git@vger.kernel.org
Cc: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Jeff King" <peff@peff.net>, "Patrick Steinhardt" <ps@pks.im>,
	"Jonathan Nieder" <jrnieder@gmail.com>,
	"Felipe Contreras" <felipe.contreras@gmail.com>
Subject: [PATCH v2 0/2] Add fetch.updateHead option
Date: Thu,  6 Apr 2023 20:37:34 -0600	[thread overview]
Message-ID: <20230407023736.49190-1-felipe.contreras@gmail.com> (raw)

It's surprising that `git clone` and `git init && git remote add -f` don't
create the same remote state.

Fix this by introducing a new configuration: `fetch.updateHead` which updates
the remote `HEAD` when it's not present with "missing", or always with
"always".

By default it's "never", which retains the current behavior.

This has already been discussed before [1].

Changes since v1:

1. Make `fetch_update_head` a named enum as suggested by Ævar
2. Remove `need_update_head`: use switch case instead, per Ævar
3. Make `update_head` receive `fetch_missing` boolean, instead of enum,
   per Ævar
4. Make `update_head` receive an unconsted `struct remote`: worse, but
   simplifies the review process

[1] https://lore.kernel.org/git/20201118091219.3341585-1-felipe.contreras@gmail.com/

Felipe Contreras (2):
  Add fetch.updateHead option
  fetch: add support for HEAD update on mirrors

 Documentation/config/fetch.txt  |  4 ++
 Documentation/config/remote.txt |  3 ++
 builtin/fetch.c                 | 76 ++++++++++++++++++++++++++++++++-
 remote.c                        | 20 +++++++++
 remote.h                        | 12 ++++++
 t/t5510-fetch.sh                | 49 +++++++++++++++++++++
 6 files changed, 163 insertions(+), 1 deletion(-)

Range-diff against v1:
1:  1cb238c83d ! 1:  0b80baba39 Add fetch.updateHead option
    @@ Commit message
     
         For the next major version of Git, we might want to change this default.
     
    +    Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
         Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
     
      ## Documentation/config/fetch.txt ##
    @@ builtin/fetch.c: static int fetch_prune_tags_config = -1; /* unspecified */
      static int prune_tags = -1; /* unspecified */
      #define PRUNE_TAGS_BY_DEFAULT 0 /* do we prune tags by default? */
      
    -+static int fetch_update_head = FETCH_UPDATE_HEAD_DEFAULT;
    ++static enum fetch_update_head fetch_update_head = FETCH_UPDATE_HEAD_DEFAULT;
     +
      static int all, append, dry_run, force, keep, multiple, update_head_ok;
      static int write_fetch_head = 1;
    @@ builtin/fetch.c: static int backfill_tags(struct transport *transport,
      	return retcode;
      }
      
    -+static void update_head(int config, const struct ref *head, const struct remote *remote)
    ++static void update_head(int fetch_missing, const struct ref *head,
    ++			struct remote *remote)
     +{
     +	char *ref, *target;
     +	const char *r;
    @@ builtin/fetch.c: static int backfill_tags(struct transport *transport,
     +	if (!head || !head->symref || !remote)
     +		return;
     +
    -+	ref = apply_refspecs((struct refspec *)&remote->fetch, "refs/heads/HEAD");
    -+	target = apply_refspecs((struct refspec *)&remote->fetch, head->symref);
    ++	ref = apply_refspecs(&remote->fetch, "refs/heads/HEAD");
    ++	target = apply_refspecs(&remote->fetch, head->symref);
     +
     +	if (!ref || !target) {
     +		warning(_("could not update remote head"));
    @@ builtin/fetch.c: static int backfill_tags(struct transport *transport,
     +	r = resolve_ref_unsafe(ref, 0, NULL, &flags);
     +
     +	if (r) {
    -+		if (config == FETCH_UPDATE_HEAD_MISSING) {
    -+			if (flags & REF_ISSYMREF)
    -+				/* already present */
    -+				return;
    -+		} else if (config == FETCH_UPDATE_HEAD_ALWAYS) {
    ++		if (!fetch_missing) {
     +			if (!strcmp(r, target))
     +				/* already up-to-date */
     +				return;
    -+		} else
    -+			/* should never happen */
    ++		} else if (flags & REF_ISSYMREF)
    ++			/* already present */
     +			return;
     +	}
     +
    @@ builtin/fetch.c: static int do_fetch(struct transport *transport,
      	int must_list_refs = 1;
      	struct fetch_head fetch_head = { 0 };
      	struct strbuf err = STRBUF_INIT;
    -+	int need_update_head = 0, update_head_config = 0;
    ++	enum fetch_update_head update_head_config = FETCH_UPDATE_HEAD_DEFAULT;
      
      	if (tags == TAGS_DEFAULT) {
      		if (transport->remote->fetch_tags == 2)
    @@ builtin/fetch.c: static int do_fetch(struct transport *transport,
     +			else
     +				update_head_config = fetch_update_head;
     +
    -+			need_update_head = update_head_config && update_head_config != FETCH_UPDATE_HEAD_NEVER;
    -+
    -+			if (need_update_head)
    ++			switch (update_head_config) {
    ++			case FETCH_UPDATE_HEAD_MISSING:
    ++			case FETCH_UPDATE_HEAD_ALWAYS:
     +				strvec_push(&transport_ls_refs_options.ref_prefixes, "HEAD");
    ++			default:
    ++				break;
    ++			}
      			refspec_ref_prefixes(&transport->remote->fetch,
      					     &transport_ls_refs_options.ref_prefixes);
     +		}
    @@ builtin/fetch.c: static int do_fetch(struct transport *transport,
      
      	commit_fetch_head(&fetch_head);
      
    -+	if (need_update_head)
    -+		update_head(update_head_config, find_ref_by_name(remote_refs, "HEAD"), transport->remote);
    ++	switch (update_head_config) {
    ++	case FETCH_UPDATE_HEAD_MISSING:
    ++	case FETCH_UPDATE_HEAD_ALWAYS:
    ++		update_head(update_head_config == FETCH_UPDATE_HEAD_MISSING,
    ++			    find_ref_by_name(remote_refs, "HEAD"),
    ++			    transport->remote);
    ++	default:
    ++		break;
    ++	}
     +
      	if (set_upstream) {
      		struct branch *branch = branch_get("HEAD");
    @@ remote.c: static void read_branches_file(struct remote_state *remote_state,
      	remote->fetch_tags = 1; /* always auto-follow */
      }
      
    -+int parse_update_head(int *r, const char *var, const char *value)
    ++int parse_update_head(enum fetch_update_head *r, const char *var,
    ++		      const char *value)
     +{
    -+	if (!r)
    -+		return -1;
    -+	else if (!value)
    ++	if (!value)
     +		return config_error_nonbool(var);
     +	else if (!strcmp(value, "never"))
     +		*r = FETCH_UPDATE_HEAD_NEVER;
    @@ remote.h: enum {
      	REMOTE_BRANCHES
      };
      
    -+enum {
    ++enum fetch_update_head {
     +	FETCH_UPDATE_HEAD_DEFAULT = 0,
     +	FETCH_UPDATE_HEAD_NEVER,
     +	FETCH_UPDATE_HEAD_MISSING,
    @@ remote.h: struct remote {
      	int prune;
      	int prune_tags;
      
    -+	int update_head;
    ++	enum fetch_update_head update_head;
     +
      	/**
      	 * The configured helper programs to run on the remote side, for
    @@ remote.h: void apply_push_cas(struct push_cas_option *, struct remote *, struct
      char *relative_url(const char *remote_url, const char *url,
      		   const char *up_path);
      
    -+int parse_update_head(int *r, const char *var, const char *value);
    ++int parse_update_head(enum fetch_update_head *r, const char *var,
    ++		      const char *value);
     +
      #endif
     
2:  fe6d62510b ! 2:  5c0f48b9cc fetch: add support for HEAD update on mirrors
    @@ Commit message
         Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
     
      ## builtin/fetch.c ##
    -@@ builtin/fetch.c: static void update_head(int config, const struct ref *head, const struct remote
    +@@ builtin/fetch.c: static void update_head(int fetch_missing, const struct ref *head,
      	if (!head || !head->symref || !remote)
      		return;
      
    --	ref = apply_refspecs((struct refspec *)&remote->fetch, "refs/heads/HEAD");
    --	target = apply_refspecs((struct refspec *)&remote->fetch, head->symref);
    +-	ref = apply_refspecs(&remote->fetch, "refs/heads/HEAD");
    +-	target = apply_refspecs(&remote->fetch, head->symref);
     +	if (!remote->mirror) {
    -+		ref = apply_refspecs((struct refspec *)&remote->fetch, "refs/heads/HEAD");
    -+		target = apply_refspecs((struct refspec *)&remote->fetch, head->symref);
    ++		ref = apply_refspecs(&remote->fetch, "refs/heads/HEAD");
    ++		target = apply_refspecs(&remote->fetch, head->symref);
      
     -	if (!ref || !target) {
     -		warning(_("could not update remote head"));
-- 
2.40.0+fc1


             reply	other threads:[~2023-04-07  2:37 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-07  2:37 Felipe Contreras [this message]
2023-04-07  2:37 ` [PATCH v2 1/2] Add fetch.updateHead option Felipe Contreras
2023-04-07  2:37 ` [PATCH v2 2/2] fetch: add support for HEAD update on mirrors Felipe Contreras

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230407023736.49190-1-felipe.contreras@gmail.com \
    --to=felipe.contreras@gmail.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=jrnieder@gmail.com \
    --cc=peff@peff.net \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).