Skip to content

Commit 9d9b0f3

Browse files
chriscoolgitster
authored andcommitted
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 <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 210d8b6 commit 9d9b0f3

8 files changed

Lines changed: 134 additions & 15 deletions

File tree

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
@@ -2580,6 +2580,8 @@ int cmd_fetch(int argc,
25802580
OPT_END()
25812581
};
25822582

2583+
filter_options.allow_auto_filter = 1;
2584+
25832585
packet_trace_identity("fetch");
25842586

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

fetch-pack.c

Lines changed: 24 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,29 @@ 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+
promisor_remote_reply(promisor_remote_config, NULL);
1669+
1670+
if (args->filter_options.choice == LOFC_AUTO) {
1671+
struct strbuf errbuf = STRBUF_INIT;
1672+
char *constructed_filter = promisor_remote_construct_filter(r);
1673+
1674+
list_objects_filter_release(&args->filter_options);
1675+
/* Disallow 'auto' as a result of the resolution of this 'auto' filter below */
1676+
args->filter_options.allow_auto_filter = 0;
1677+
1678+
if (constructed_filter &&
1679+
gently_parse_list_objects_filter(&args->filter_options,
1680+
constructed_filter,
1681+
&errbuf))
1682+
die(_("couldn't resolve 'auto' filter '%s': %s"),
1683+
constructed_filter, errbuf.buf);
1684+
1685+
free(constructed_filter);
1686+
strbuf_release(&errbuf);
1687+
}
16641688

16651689
negotiator = &negotiator_alloc;
16661690
if (args->refetch)

t/t5710-promisor-remote-capability.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,66 @@ test_expect_success "clone with promisor.storeFields=partialCloneFilter" '
423423
test_grep "'\''blob:limit=8k'\'' -> '\''blob:limit=7k'\''" err
424424
'
425425

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

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)