Skip to content

Commit b87ade4

Browse files
committed
fetch-pack: wire up and enable auto filter logic
Previous commits have set up an infrastructure for `--filter=auto` to automatically prepare a partial clone filter based on what the server advertised and the client accepted. Using that infrastructure, let's now enable the `--filter=auto` option in `git clone` and `git fetch` by setting `allow_auto_filter` to 1. Note that these small changes mean that when `git clone --filter=auto` or `git fetch --filter=auto` are used, "auto" is automatically saved as the partial clone filter for the server on the client. Therefore subsequent calls to `git fetch` on the client will automatically use this "auto" mode even without `--filter=auto`. Let's also set `allow_auto_filter` to 1 in `transport.c`, as the transport layer must be able to accept the "auto" filter spec even if the invoking command hasn't fully parsed it yet. When an "auto" filter is requested, let's have the "fetch-pack.c" code in `do_fetch_pack_v2()` compute a filter and send it to the server. In `do_fetch_pack_v2()` the logic also needs to check for the "promisor-remote" capability and call `promisor_remote_reply()` to parse advertised remotes and populate the list of those accepted (and their filters). Signed-off-by: Christian Couder <[email protected]>
1 parent c5fac5f commit b87ade4

File tree

8 files changed

+130
-15
lines changed

8 files changed

+130
-15
lines changed

Documentation/fetch-options.adoc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,20 @@ precedence over the `fetch.output` config option.
9292
Use the partial clone feature and request that the server sends
9393
a subset of reachable objects according to a given object filter.
9494
When using `--filter`, the supplied _<filter-spec>_ is used for
95-
the partial fetch. For example, `--filter=blob:none` will filter
96-
out all blobs (file contents) until needed by Git. Also,
97-
`--filter=blob:limit=<size>` will filter out all blobs of size
98-
at least _<size>_. For more details on filter specifications, see
99-
the `--filter` option in linkgit:git-rev-list[1].
95+
the partial fetch.
96+
+
97+
If `--filter=auto` is used, the filter specification is determined
98+
automatically by combining the filter specifications advertised by
99+
the server for the promisor remotes that the client accepts (see
100+
linkgit:gitprotocol-v2[5] and the `promisor.acceptFromServer`
101+
configuration option in linkgit:git-config[1]).
102+
+
103+
For details on all other available filter specifications, see the
104+
`--filter=<filter-spec>` option in linkgit:git-rev-list[1].
105+
+
106+
For example, `--filter=blob:none` will filter out all blobs (file
107+
contents) until needed by Git. Also, `--filter=blob:limit=<size>` will
108+
filter out all blobs of size at least _<size>_.
100109

101110
ifndef::git-pull[]
102111
`--write-fetch-head`::

Documentation/git-clone.adoc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,26 @@ objects from the source repository into a pack in the cloned repository.
187187
Use the partial clone feature and request that the server sends
188188
a subset of reachable objects according to a given object filter.
189189
When using `--filter`, the supplied _<filter-spec>_ is used for
190-
the partial clone filter. For example, `--filter=blob:none` will
191-
filter out all blobs (file contents) until needed by Git. Also,
192-
`--filter=blob:limit=<size>` will filter out all blobs of size
193-
at least _<size>_. For more details on filter specifications, see
194-
the `--filter` option in linkgit:git-rev-list[1].
190+
the partial clone filter.
191+
+
192+
If `--filter=auto` is used the filter specification is determined
193+
automatically through the 'promisor-remote' protocol (see
194+
linkgit:gitprotocol-v2[5]) by combining the filter specifications
195+
advertised by the server for the promisor remotes that the client
196+
accepts (see the `promisor.acceptFromServer` configuration option in
197+
linkgit:git-config[1]). This allows the server to suggest the optimal
198+
filter for the available promisor remotes.
199+
+
200+
As with other filter specifications, the "auto" value is persisted in
201+
the configuration. This ensures that future fetches will continue to
202+
adapt to the server's current recommendation.
203+
+
204+
For details on all other available filter specifications, see the
205+
`--filter=<filter-spec>` option in linkgit:git-rev-list[1].
206+
+
207+
For example, `--filter=blob:none` will filter out all blobs (file
208+
contents) until needed by Git. Also, `--filter=blob:limit=<size>` will
209+
filter out all blobs of size at least _<size>_.
195210

196211
`--also-filter-submodules`::
197212
Also apply the partial clone filter to any submodules in the repository.

Documentation/gitprotocol-v2.adoc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -812,10 +812,15 @@ MUST appear first in each pr-fields, in that order.
812812
After these mandatory fields, the server MAY advertise the following
813813
optional fields in any order:
814814
815-
`partialCloneFilter`:: The filter specification used by the remote.
815+
`partialCloneFilter`:: The filter specification for the remote. It
816+
corresponds to the "remote.<name>.partialCloneFilter" config setting.
816817
Clients can use this to determine if the remote's filtering strategy
817-
is compatible with their needs (e.g., checking if both use "blob:none").
818-
It corresponds to the "remote.<name>.partialCloneFilter" config setting.
818+
is compatible with their needs (e.g., checking if both use
819+
"blob:none"). Additionally they can use this through the
820+
`--filter=auto` option in linkgit:git-clone[1]. With that option, the
821+
filter specification of the clone will be automatically computed by
822+
combining the filter specifications of the promisor remotes the client
823+
accepts.
819824
820825
`token`:: An authentication token that clients can use when
821826
connecting to the remote. It corresponds to the "remote.<name>.token"
@@ -828,8 +833,9 @@ future protocol extensions.
828833
829834
The client can use information transmitted through these fields to
830835
decide if it accepts the advertised promisor remote. Also, the client
831-
can be configured to store the values of these fields (see
832-
"promisor.storeFields" in linkgit:git-config[1]).
836+
can be configured to store the values of these fields or use them
837+
to automatically configure the repository (see "promisor.storeFields"
838+
in linkgit:git-config[1] and `--filter=auto` in linkgit:git-clone[1]).
833839
834840
Field values MUST be urlencoded.
835841

builtin/clone.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,8 @@ int cmd_clone(int argc,
10011001
NULL
10021002
};
10031003

1004+
filter_options.allow_auto_filter = 1;
1005+
10041006
packet_trace_identity("clone");
10051007

10061008
repo_config(the_repository, git_clone_config, NULL);

builtin/fetch.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,8 @@ int cmd_fetch(int argc,
24392439
OPT_END()
24402440
};
24412441

2442+
filter_options.allow_auto_filter = 1;
2443+
24422444
packet_trace_identity("fetch");
24432445

24442446
/* Record the command line for the reflog */

fetch-pack.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "sigchain.h"
3636
#include "mergesort.h"
3737
#include "prio-queue.h"
38+
#include "promisor-remote.h"
3839

3940
static int transfer_unpack_limit = -1;
4041
static int fetch_unpack_limit = -1;
@@ -1661,6 +1662,25 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
16611662
struct string_list packfile_uris = STRING_LIST_INIT_DUP;
16621663
int i;
16631664
struct strvec index_pack_args = STRVEC_INIT;
1665+
const char *promisor_remote_config;
1666+
1667+
if (server_feature_v2("promisor-remote", &promisor_remote_config)) {
1668+
char *remote_name = promisor_remote_reply(promisor_remote_config);
1669+
free(remote_name);
1670+
}
1671+
1672+
if (args->filter_options.choice == LOFC_AUTO) {
1673+
struct strbuf errbuf = STRBUF_INIT;
1674+
char *constructed_filter = promisor_remote_construct_filter(r);
1675+
1676+
list_objects_filter_resolve_auto(&args->filter_options,
1677+
constructed_filter, &errbuf);
1678+
if (errbuf.len > 0)
1679+
die(_("couldn't resolve 'auto' filter: %s"), errbuf.buf);
1680+
1681+
free(constructed_filter);
1682+
strbuf_release(&errbuf);
1683+
}
16641684

16651685
negotiator = &negotiator_alloc;
16661686
if (args->refetch)

t/t5710-promisor-remote-capability.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,66 @@ test_expect_success "clone with promisor.storeFields=partialCloneFilter" '
409409
check_missing_objects server 1 "$oid"
410410
'
411411

412+
test_expect_success "clone and fetch with --filter=auto" '
413+
git -C server config promisor.advertise true &&
414+
test_when_finished "rm -rf client trace" &&
415+
416+
git -C server config remote.lop.partialCloneFilter "blob:limit=9500" &&
417+
test_config -C server promisor.sendFields "partialCloneFilter" &&
418+
419+
GIT_TRACE_PACKET="$(pwd)/trace" GIT_NO_LAZY_FETCH=0 git clone \
420+
-c remote.lop.promisor=true \
421+
-c remote.lop.url="file://$(pwd)/lop" \
422+
-c promisor.acceptfromserver=All \
423+
--no-local --filter=auto server client 2>err &&
424+
425+
test_grep "filter blob:limit=9500" trace &&
426+
test_grep ! "filter auto" trace &&
427+
428+
# Verify "auto" is persisted in config
429+
echo auto >expected &&
430+
git -C client config remote.origin.partialCloneFilter >actual &&
431+
test_cmp expected actual &&
432+
433+
# Check that the largest object is still missing on the server
434+
check_missing_objects server 1 "$oid" &&
435+
436+
# Now change the filter on the server
437+
git -C server config remote.lop.partialCloneFilter "blob:limit=5678" &&
438+
439+
# Get a new commit on the server to ensure "git fetch" actually runs fetch-pack
440+
test_commit -C template new-commit &&
441+
git -C template push --all "$(pwd)/server" &&
442+
443+
# Perform a fetch WITH --filter=auto
444+
rm -rf trace &&
445+
GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch --filter=auto &&
446+
447+
# Verify that the new filter was used
448+
test_grep "filter blob:limit=5678" trace &&
449+
450+
# Check that the largest object is still missing on the server
451+
check_missing_objects server 1 "$oid" &&
452+
453+
# Change the filter on the server again
454+
git -C server config remote.lop.partialCloneFilter "blob:limit=5432" &&
455+
456+
# Get yet a new commit on the server to ensure fetch-pack runs
457+
test_commit -C template yet-a-new-commit &&
458+
git -C template push --all "$(pwd)/server" &&
459+
460+
# Perform a fetch WITHOUT --filter=auto
461+
# Relies on "auto" being persisted in the client config
462+
rm -rf trace &&
463+
GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch &&
464+
465+
# Verify that the new filter was used
466+
test_grep "filter blob:limit=5432" trace &&
467+
468+
# Check that the largest object is still missing on the server
469+
check_missing_objects server 1 "$oid"
470+
'
471+
412472
test_expect_success "clone with promisor.advertise set to 'true' but don't delete the client" '
413473
git -C server config promisor.advertise true &&
414474

transport.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
12191219
*/
12201220
struct git_transport_data *data = xcalloc(1, sizeof(*data));
12211221
list_objects_filter_init(&data->options.filter_options);
1222+
data->options.filter_options.allow_auto_filter = 1;
12221223
ret->data = data;
12231224
ret->vtable = &builtin_smart_vtable;
12241225
ret->smart_options = &(data->options);

0 commit comments

Comments
 (0)