diff mbox series

[v3,4/7] fetch: add --refetch option

Message ID a503b98f33328133f9a89ad7eba986b73535c461.1646406275.git.gitgitgadget@gmail.com (mailing list archive)
State Accepted
Commit 3c7bab06e12922fbcb375187eb60ac426fc72a3a
Headers show
Series fetch: add repair: full refetch without negotiation (was: "refiltering") | expand

Commit Message

Robert Coup March 4, 2022, 3:04 p.m. UTC
From: Robert Coup <robert@coup.net.nz>

Teach fetch and transports the --refetch option to force a full fetch
without negotiating common commits with the remote. Use when applying a
new partial clone filter to refetch all matching objects.

Signed-off-by: Robert Coup <robert@coup.net.nz>
---
 Documentation/fetch-options.txt |  9 +++++++++
 builtin/fetch.c                 | 15 ++++++++++++++-
 transport-helper.c              |  3 +++
 transport.c                     |  4 ++++
 transport.h                     |  4 ++++
 5 files changed, 34 insertions(+), 1 deletion(-)

Comments

Junio C Hamano March 4, 2022, 9:19 p.m. UTC | #1
"Robert Coup via GitGitGadget" <gitgitgadget@gmail.com> writes:

> +static int verbosity, deepen_relative, set_upstream, refetch;
>  static int progress = -1;
>  static int enable_auto_gc = 1;
>  static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
> @@ -190,6 +190,9 @@ static struct option builtin_fetch_options[] = {
>  	OPT_SET_INT_F(0, "unshallow", &unshallow,
>  		      N_("convert to a complete repository"),
>  		      1, PARSE_OPT_NONEG),
> +	OPT_SET_INT_F(0, "refetch", &refetch,
> +		      N_("re-fetch without negotiating common commits"),
> +		      1, PARSE_OPT_NONEG),

I guess the existing --unshallow has the same problem, but it strikes
me odd that these aren't doing a bog-standard OPT_BOOL(), with default
value of "false", like, say "--update-head-ok" does.

That will naturally support things like

	git fetch --refetch --no-refetch

where a later option overrides what an earlier option did.
Robert Coup March 7, 2022, 11:31 a.m. UTC | #2
Hi Junio,

On Fri, 4 Mar 2022 at 21:19, Junio C Hamano <gitster@pobox.com> wrote:
> I guess the existing --unshallow has the same problem, but it strikes
> me odd that these aren't doing a bog-standard OPT_BOOL(), with default
> value of "false", like, say "--update-head-ok" does.
>
> That will naturally support things like
>
>         git fetch --refetch --no-refetch
>
> where a later option overrides what an earlier option did.
>

Ah, I literally copied the unshallow one since it seemed boolean-ish
and that's what I wanted. I'll look into it.

Thanks,
Rob :)
Junio C Hamano March 7, 2022, 5:27 p.m. UTC | #3
Robert Coup <robert@coup.net.nz> writes:

> Ah, I literally copied the unshallow one since it seemed boolean-ish
> and that's what I wanted. I'll look into it.

You may (or may not --- I didn't look) find options that need to be
OPT_BOOL() other than "unshallow" one.

While it would be excellent to add a separate "preliminary clean-up"
step before you add OPT_BOOL("refetch") to fix them to use
OPT_BOOL() instead of OPT_SET_INT(), that will add extra review
cycles to the series by extending the scope of it.

It is OK to leave them, in addition to the new one you are adding,
to use the old and a bit incorrect pattern, as long as you leave a
prominent note that we need to clean them up later.

Thanks.
Robert Coup March 9, 2022, 10 a.m. UTC | #4
Hi Junio,

On Mon, 7 Mar 2022 at 17:27, Junio C Hamano <gitster@pobox.com> wrote:
>
> You may (or may not --- I didn't look) find options that need to be
> OPT_BOOL() other than "unshallow" one.
>
> While it would be excellent to add a separate "preliminary clean-up"
> step before you add OPT_BOOL("refetch") to fix them to use
> OPT_BOOL() instead of OPT_SET_INT(), that will add extra review
> cycles to the series by extending the scope of it.
>
> It is OK to leave them, in addition to the new one you are adding,
> to use the old and a bit incorrect pattern, as long as you leave a
> prominent note that we need to clean them up later.

I think for this series I will just do a re-roll updating refetch to
use OPT_BOOL, and I can do a separate series to look for other
existing booleans using OPT_SET_INT.

Rob :)
diff mbox series

Patch

diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index f9036831898..21a247abfa4 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -163,6 +163,15 @@  endif::git-pull[]
 	behavior for a remote may be specified with the remote.<name>.tagOpt
 	setting. See linkgit:git-config[1].
 
+ifndef::git-pull[]
+--refetch::
+	Instead of negotiating with the server to avoid transferring commits and
+	associated objects that are already present locally, this option fetches
+	all objects as a fresh clone would. Use this to reapply a partial clone
+	filter from configuration or using `--filter=` when the filter
+	definition has changed.
+endif::git-pull[]
+
 --refmap=<refspec>::
 	When fetching refs listed on the command line, use the
 	specified refspec (can be given more than once) to map the
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 95832ba1dfd..f7bcf6fa64d 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -59,7 +59,7 @@  static int prune_tags = -1; /* unspecified */
 
 static int all, append, dry_run, force, keep, multiple, update_head_ok;
 static int write_fetch_head = 1;
-static int verbosity, deepen_relative, set_upstream;
+static int verbosity, deepen_relative, set_upstream, refetch;
 static int progress = -1;
 static int enable_auto_gc = 1;
 static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
@@ -190,6 +190,9 @@  static struct option builtin_fetch_options[] = {
 	OPT_SET_INT_F(0, "unshallow", &unshallow,
 		      N_("convert to a complete repository"),
 		      1, PARSE_OPT_NONEG),
+	OPT_SET_INT_F(0, "refetch", &refetch,
+		      N_("re-fetch without negotiating common commits"),
+		      1, PARSE_OPT_NONEG),
 	{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
 		   N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
 	OPT_CALLBACK_F(0, "recurse-submodules-default",
@@ -1296,6 +1299,14 @@  static int check_exist_and_connected(struct ref *ref_map)
 	if (deepen)
 		return -1;
 
+	/*
+	 * Similarly, if we need to refetch, we always want to perform a full
+	 * fetch ignoring existing objects.
+	 */
+	if (refetch)
+		return -1;
+
+
 	/*
 	 * check_connected() allows objects to merely be promised, but
 	 * we need all direct targets to exist.
@@ -1492,6 +1503,8 @@  static struct transport *prepare_transport(struct remote *remote, int deepen)
 		set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes");
 	if (update_shallow)
 		set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
+	if (refetch)
+		set_option(transport, TRANS_OPT_REFETCH, "yes");
 	if (filter_options.choice) {
 		const char *spec =
 			expand_list_objects_filter_spec(&filter_options);
diff --git a/transport-helper.c b/transport-helper.c
index a0297b0986c..b4dbbabb0c2 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -715,6 +715,9 @@  static int fetch_refs(struct transport *transport,
 	if (data->transport_options.update_shallow)
 		set_helper_option(transport, "update-shallow", "true");
 
+	if (data->transport_options.refetch)
+		set_helper_option(transport, "refetch", "true");
+
 	if (data->transport_options.filter_options.choice) {
 		const char *spec = expand_list_objects_filter_spec(
 			&data->transport_options.filter_options);
diff --git a/transport.c b/transport.c
index 253d6671b1f..e2817b7a715 100644
--- a/transport.c
+++ b/transport.c
@@ -243,6 +243,9 @@  static int set_git_option(struct git_transport_options *opts,
 		list_objects_filter_die_if_populated(&opts->filter_options);
 		parse_list_objects_filter(&opts->filter_options, value);
 		return 0;
+	} else if (!strcmp(name, TRANS_OPT_REFETCH)) {
+		opts->refetch = !!value;
+		return 0;
 	} else if (!strcmp(name, TRANS_OPT_REJECT_SHALLOW)) {
 		opts->reject_shallow = !!value;
 		return 0;
@@ -377,6 +380,7 @@  static int fetch_refs_via_pack(struct transport *transport,
 	args.update_shallow = data->options.update_shallow;
 	args.from_promisor = data->options.from_promisor;
 	args.filter_options = data->options.filter_options;
+	args.refetch = data->options.refetch;
 	args.stateless_rpc = transport->stateless_rpc;
 	args.server_options = transport->server_options;
 	args.negotiation_tips = data->options.negotiation_tips;
diff --git a/transport.h b/transport.h
index a0bc6a1e9eb..12bc08fc339 100644
--- a/transport.h
+++ b/transport.h
@@ -16,6 +16,7 @@  struct git_transport_options {
 	unsigned update_shallow : 1;
 	unsigned reject_shallow : 1;
 	unsigned deepen_relative : 1;
+	unsigned refetch : 1;
 
 	/* see documentation of corresponding flag in fetch-pack.h */
 	unsigned from_promisor : 1;
@@ -216,6 +217,9 @@  void transport_check_allowed(const char *type);
 /* Filter objects for partial clone and fetch */
 #define TRANS_OPT_LIST_OBJECTS_FILTER "filter"
 
+/* Refetch all objects without negotiating */
+#define TRANS_OPT_REFETCH "refetch"
+
 /* Request atomic (all-or-nothing) updates when pushing */
 #define TRANS_OPT_ATOMIC "atomic"