From: "Shubham Kanodia via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "Patrick Steinhardt [ ]" <ps@pks.im>,
"Junio C Hamano [ ]" <gitster@pobox.com>,
Derrick Stolee <stolee@gmail.com>,
Shubham Kanodia <shubham.kanodia10@gmail.com>,
Shubham Kanodia <shubham.kanodia10@gmail.com>
Subject: [PATCH v2] remote: prefetch config
Date: Thu, 05 Sep 2024 02:52:05 +0000 [thread overview]
Message-ID: <pull.1779.v2.git.1725504725976.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1779.git.1725472799637.gitgitgadget@gmail.com>
From: Shubham Kanodia <shubham.kanodia10@gmail.com>
Large repositories often contain numerous branches and refs, many of
which individual users may not need. This commit introduces a new
configuration option (`remote.<remote>.prefetch`) to allow
users to specify which remotes to prefetch during
the maintenance task.
Key behaviors:
1. If `remote.<remote>.prefetch` is unset or true, running
`git-maintenance` will prefetch all refs for the remote.
2. If `remote.<remote>.prefetch` is set to false, the remote
will be ignored for prefetching.
In a future change, we could also allow restricting the refs that are
prefetched per remote using the `prefetchref` config option per remote.
Both of these options in unison would allow users to optimize their
prefetch operations, reducing network traffic and disk usage.
Signed-off-by: Shubham Kanodia <shubham.kanodia10@gmail.com>
---
remote: prefetch config
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1779%2Fpastelsky%2Fsk%2Fmaintenance-prefetch-remote-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1779/pastelsky/sk/maintenance-prefetch-remote-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1779
Range-diff vs v1:
1: 667553b114b ! 1: 1d58b782e22 remote: prefetch config
@@ builtin/gc.c: static int fetch_remote(struct remote *remote, void *cbdata)
if (remote->skip_default_update)
return 0;
-+ if (remote->prefetch == 0)
++ if (!remote->prefetch)
+ return 0;
+
child.git_cmd = 1;
@@ remote.h: struct remote {
struct refspec fetch;
+ /*
-+ * This setting for whether to prefetch from a remote
++ * The setting for whether to prefetch from a remote
+ * when a fetch is invoked with a prefetch flag.
+ * -1 = unset
+ * 0 = don't prefetch from this remote
@@ t/t7900-maintenance.sh: test_expect_success 'prefetch multiple remotes' '
+ # Run maintenance prefetch task
+ GIT_TRACE2_EVENT="$(pwd)/prefetch.txt" git maintenance run --task=prefetch 2>/dev/null &&
+
-+ # Check that remote1 was not fetched (prefetch=false)
-+ test_subcommand ! git fetch remote1 --prefetch --prune --no-tags \
-+ --no-write-fetch-head --recurse-submodules=no --quiet \
-+ <prefetch.txt &&
-+
-+ # Check that remote2 was fetched (prefetch=true)
-+ test_subcommand git fetch remote2 --prefetch --prune --no-tags \
-+ --no-write-fetch-head --recurse-submodules=no --quiet \
-+ <prefetch.txt &&
-+
-+ # Check that remote3 was fetched (prefetch unset, default to true)
-+ test_subcommand git fetch remote3 --prefetch --prune --no-tags \
-+ --no-write-fetch-head --recurse-submodules=no --quiet \
-+ <prefetch.txt &&
++ # Check that if remotes were prefetched properly
++ fetchargs="--prefetch --prune --no-tags --no-write-fetch-head --recurse-submodules=no --quiet" &&
++ test_subcommand ! git fetch remote1 $fetchargs <prefetch.txt &&
++ test_subcommand git fetch remote2 $fetchargs <prefetch.txt &&
++ test_subcommand git fetch remote3 $fetchargs <prefetch.txt &&
+
+ # Verify that changes are in the prefetch refs for remote2 and remote3, but not remote1
+ test_must_fail git rev-parse refs/prefetch/remotes/remote1/one &&
Documentation/config/remote.txt | 5 ++++
Documentation/git-maintenance.txt | 7 +++---
builtin/gc.c | 3 +++
remote.c | 3 +++
remote.h | 9 +++++++
t/t7900-maintenance.sh | 42 +++++++++++++++++++++++++++++++
6 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/Documentation/config/remote.txt b/Documentation/config/remote.txt
index 8efc53e836d..c2b3876192c 100644
--- a/Documentation/config/remote.txt
+++ b/Documentation/config/remote.txt
@@ -33,6 +33,11 @@ remote.<name>.fetch::
The default set of "refspec" for linkgit:git-fetch[1]. See
linkgit:git-fetch[1].
+remote.<name>.prefetch::
+ If false, refs from the remote would not be prefetched for
+ the prefetch task in linkgit:git-maintenance[1]. If not set,
+ the value is assumed to be true.
+
remote.<name>.push::
The default set of "refspec" for linkgit:git-push[1]. See
linkgit:git-push[1].
diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt
index 51d0f7e94b6..2fd38706ea2 100644
--- a/Documentation/git-maintenance.txt
+++ b/Documentation/git-maintenance.txt
@@ -97,9 +97,10 @@ commit-graph::
prefetch::
The `prefetch` task updates the object directory with the latest
- objects from all registered remotes. For each remote, a `git fetch`
- command is run. The configured refspec is modified to place all
- requested refs within `refs/prefetch/`. Also, tags are not updated.
+ objects from all registered remotes unless they've disabled prefetch
+ using `remote.<remote>.prefetch` set to `false`. For each such remote,
+ a `git fetch` command is run. The configured refspec is modified to place
+ all requested refs within `refs/prefetch/`. Also, tags are not updated.
+
This is done to avoid disrupting the remote-tracking branches. The end users
expect these refs to stay unmoved unless they initiate a fetch. However,
diff --git a/builtin/gc.c b/builtin/gc.c
index 427faf1cfe1..2ca3a3e7d6a 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1027,6 +1027,9 @@ static int fetch_remote(struct remote *remote, void *cbdata)
if (remote->skip_default_update)
return 0;
+ if (!remote->prefetch)
+ return 0;
+
child.git_cmd = 1;
strvec_pushl(&child.args, "fetch", remote->name,
"--prefetch", "--prune", "--no-tags",
diff --git a/remote.c b/remote.c
index 8f3dee13186..05edb3a5f40 100644
--- a/remote.c
+++ b/remote.c
@@ -140,6 +140,7 @@ static struct remote *make_remote(struct remote_state *remote_state,
CALLOC_ARRAY(ret, 1);
ret->prune = -1; /* unspecified */
ret->prune_tags = -1; /* unspecified */
+ ret->prefetch = -1; /* unspecified */
ret->name = xstrndup(name, len);
refspec_init(&ret->push, REFSPEC_PUSH);
refspec_init(&ret->fetch, REFSPEC_FETCH);
@@ -456,6 +457,8 @@ static int handle_config(const char *key, const char *value,
remote->prune = git_config_bool(key, value);
else if (!strcmp(subkey, "prunetags"))
remote->prune_tags = git_config_bool(key, value);
+ else if (!strcmp(subkey, "prefetch"))
+ remote->prefetch = git_config_bool(key, value);
else if (!strcmp(subkey, "url")) {
if (!value)
return config_error_nonbool(key);
diff --git a/remote.h b/remote.h
index b901b56746d..4522fdec354 100644
--- a/remote.h
+++ b/remote.h
@@ -77,6 +77,15 @@ struct remote {
struct refspec fetch;
+ /*
+ * The setting for whether to prefetch from a remote
+ * when a fetch is invoked with a prefetch flag.
+ * -1 = unset
+ * 0 = don't prefetch from this remote
+ * 1 = prefetch from this remote
+ */
+ int prefetch;
+
/*
* The setting for whether to fetch tags (as a separate rule from the
* configured refspecs);
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index abae7a97546..7484e1f1d46 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -245,6 +245,48 @@ test_expect_success 'prefetch multiple remotes' '
test_subcommand git fetch remote2 $fetchargs <skip-remote1.txt
'
+test_expect_success 'prefetch respects remote.*.prefetch config' '
+ test_create_repo prefetch-test-config &&
+ (
+ cd prefetch-test-config &&
+ test_commit initial &&
+ test_create_repo clone1 &&
+ test_create_repo clone2 &&
+ test_create_repo clone3 &&
+
+ git remote add remote1 "file://$(pwd)/clone1" &&
+ git remote add remote2 "file://$(pwd)/clone2" &&
+ git remote add remote3 "file://$(pwd)/clone3" &&
+
+ git config remote.remote1.prefetch false &&
+ git config remote.remote2.prefetch true &&
+ # remote3 is left unset
+
+ # Make changes in all clones
+ git -C clone1 switch -c one &&
+ git -C clone2 switch -c two &&
+ git -C clone3 switch -c three &&
+ test_commit -C clone1 one &&
+ test_commit -C clone2 two &&
+ test_commit -C clone3 three &&
+
+ # Run maintenance prefetch task
+ GIT_TRACE2_EVENT="$(pwd)/prefetch.txt" git maintenance run --task=prefetch 2>/dev/null &&
+
+ # Check that if remotes were prefetched properly
+ fetchargs="--prefetch --prune --no-tags --no-write-fetch-head --recurse-submodules=no --quiet" &&
+ test_subcommand ! git fetch remote1 $fetchargs <prefetch.txt &&
+ test_subcommand git fetch remote2 $fetchargs <prefetch.txt &&
+ test_subcommand git fetch remote3 $fetchargs <prefetch.txt &&
+
+ # Verify that changes are in the prefetch refs for remote2 and remote3, but not remote1
+ test_must_fail git rev-parse refs/prefetch/remotes/remote1/one &&
+ git fetch --all &&
+ test_cmp_rev refs/remotes/remote2/two refs/prefetch/remotes/remote2/two &&
+ test_cmp_rev refs/remotes/remote3/three refs/prefetch/remotes/remote3/three
+ )
+'
+
test_expect_success 'loose-objects task' '
# Repack everything so we know the state of the object dir
git repack -adk &&
base-commit: 2e7b89e038c0c888acf61f1b4ee5a43d4dd5e94c
--
gitgitgadget
next prev parent reply other threads:[~2024-09-05 2:52 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-04 17:59 [PATCH] remote: prefetch config Shubham Kanodia via GitGitGadget
2024-09-04 20:03 ` Derrick Stolee
2024-09-04 20:55 ` Junio C Hamano
2024-09-05 2:08 ` Derrick Stolee
2024-09-05 2:51 ` Shubham Kanodia
2024-09-05 15:00 ` Junio C Hamano
2024-09-05 2:52 ` Shubham Kanodia via GitGitGadget [this message]
2024-09-05 16:06 ` [PATCH v2] " Junio C Hamano
2024-09-05 16:43 ` Shubham Kanodia
2024-09-05 16:52 ` Junio C Hamano
2024-09-05 17:19 ` Shubham Kanodia
2024-09-05 17:54 ` Junio C Hamano
2024-09-05 16:45 ` [PATCH v3] " Shubham Kanodia via GitGitGadget
2024-09-05 19:43 ` [PATCH v4] " Shubham Kanodia via GitGitGadget
2024-09-05 20:57 ` Junio C Hamano
2024-09-06 9:42 ` Shubham Kanodia
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.1779.v2.git.1725504725976.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=ps@pks.im \
--cc=shubham.kanodia10@gmail.com \
--cc=stolee@gmail.com \
/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.
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 NNTP newsgroup(s).