Skip to content

Commit 4b88a53

Browse files
committed
Merge branch 'cc/lop-filter-auto' into seen
"auto filter" logic for large-object promisor remote. Comments? * cc/lop-filter-auto: fetch-pack: wire up and enable auto filter logic promisor-remote: keep advertised filters in memory list-objects-filter-options: support 'auto' mode for --filter doc: fetch: document `--filter=<filter-spec>` option fetch: make filter_options local to cmd_fetch() clone: make filter_options local to cmd_clone() promisor-remote: allow a client to store fields promisor-remote: refactor initialising field lists
2 parents cc438d5 + 8e3ebdd commit 4b88a53

17 files changed

Lines changed: 597 additions & 56 deletions

Documentation/config/promisor.adoc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,36 @@ variable. The fields are checked only if the
8989
`promisor.acceptFromServer` config variable is not set to "None". If
9090
set to "None", this config variable has no effect. See
9191
linkgit:gitprotocol-v2[5].
92+
93+
promisor.storeFields::
94+
A comma or space separated list of additional remote related
95+
field names. If a client accepts an advertised remote, the
96+
client will store the values associated with these field names
97+
taken from the remote advertisement into its configuration,
98+
and then reload its remote configuration. Currently,
99+
"partialCloneFilter" and "token" are the only supported field
100+
names.
101+
+
102+
For example if a server advertises "partialCloneFilter=blob:limit=20k"
103+
for remote "foo", and that remote is accepted, then "blob:limit=20k"
104+
will be stored for the "remote.foo.partialCloneFilter" configuration
105+
variable.
106+
+
107+
If the new field value from an advertised remote is the same as the
108+
existing field value for that remote on the client side, then no
109+
change is made to the client configuration though.
110+
+
111+
When a new value is stored, a message is printed to standard error to
112+
let users know about this.
113+
+
114+
Note that for security reasons, if the remote is not already
115+
configured on the client side, nothing will be stored for that
116+
remote. In any case, no new remote will be created and no URL will be
117+
stored.
118+
+
119+
Before storing a partial clone filter, it's parsed to check it's
120+
valid. If it's not, a warning is emitted and it's not stored.
121+
+
122+
Before storing a token, a check is performed to ensure it contains no
123+
control character. If the check fails, a warning is emitted and it's
124+
not stored.

Documentation/fetch-options.adoc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,25 @@ linkgit:git-config[1].
8888
This is incompatible with `--recurse-submodules=(yes|on-demand)` and takes
8989
precedence over the `fetch.output` config option.
9090

91+
`--filter=<filter-spec>`::
92+
Use the partial clone feature and request that the server sends
93+
a subset of reachable objects according to a given object filter.
94+
When using `--filter`, the supplied _<filter-spec>_ is used for
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>_.
109+
91110
ifndef::git-pull[]
92111
`--write-fetch-head`::
93112
`--no-write-fetch-head`::

Documentation/git-clone.adoc

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

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

Documentation/gitprotocol-v2.adoc

Lines changed: 16 additions & 8 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"
@@ -826,9 +831,11 @@ are case-sensitive and MUST be transmitted exactly as specified
826831
above. Clients MUST ignore fields they don't recognize to allow for
827832
future protocol extensions.
828833
829-
For now, the client can only use information transmitted through these
830-
fields to decide if it accepts the advertised promisor remote. In the
831-
future that information might be used for other purposes though.
834+
The client can use information transmitted through these fields to
835+
decide if it accepts the advertised promisor remote. Also, the client
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]).
832839
833840
Field values MUST be urlencoded.
834841
@@ -856,8 +863,9 @@ the server advertised, the client shouldn't advertise the
856863
On the server side, the "promisor.advertise" and "promisor.sendFields"
857864
configuration options can be used to control what it advertises. On
858865
the client side, the "promisor.acceptFromServer" configuration option
859-
can be used to control what it accepts. See the documentation of these
860-
configuration options for more information.
866+
can be used to control what it accepts, and the "promisor.storeFields"
867+
option, to control what it stores. See the documentation of these
868+
configuration options in linkgit:git-config[1] for more information.
861869
862870
Note that in the future it would be nice if the "promisor-remote"
863871
protocol capability could be used by the server, when responding to

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,7 @@ CLAR_TEST_SUITES += u-dir
15211521
CLAR_TEST_SUITES += u-example-decorate
15221522
CLAR_TEST_SUITES += u-hash
15231523
CLAR_TEST_SUITES += u-hashmap
1524+
CLAR_TEST_SUITES += u-list-objects-filter-options
15241525
CLAR_TEST_SUITES += u-mem-pool
15251526
CLAR_TEST_SUITES += u-oid-array
15261527
CLAR_TEST_SUITES += u-oidmap

builtin/clone.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ static struct string_list option_required_reference = STRING_LIST_INIT_NODUP;
7777
static struct string_list option_optional_reference = STRING_LIST_INIT_NODUP;
7878
static int max_jobs = -1;
7979
static struct string_list option_recurse_submodules = STRING_LIST_INIT_NODUP;
80-
static struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
8180
static int config_filter_submodules = -1; /* unspecified */
8281
static int option_remote_submodules;
8382

@@ -634,7 +633,9 @@ static int git_sparse_checkout_init(const char *repo)
634633
return result;
635634
}
636635

637-
static int checkout(int submodule_progress, int filter_submodules,
636+
static int checkout(int submodule_progress,
637+
struct list_objects_filter_options *filter_options,
638+
int filter_submodules,
638639
enum ref_storage_format ref_storage_format)
639640
{
640641
struct object_id oid;
@@ -723,9 +724,9 @@ static int checkout(int submodule_progress, int filter_submodules,
723724
strvec_pushf(&cmd.args, "--ref-format=%s",
724725
ref_storage_format_to_name(ref_storage_format));
725726

726-
if (filter_submodules && filter_options.choice)
727+
if (filter_submodules && filter_options->choice)
727728
strvec_pushf(&cmd.args, "--filter=%s",
728-
expand_list_objects_filter_spec(&filter_options));
729+
expand_list_objects_filter_spec(filter_options));
729730

730731
if (option_single_branch >= 0)
731732
strvec_push(&cmd.args, option_single_branch ?
@@ -903,6 +904,7 @@ int cmd_clone(int argc,
903904
enum transport_family family = TRANSPORT_FAMILY_ALL;
904905
struct string_list option_config = STRING_LIST_INIT_DUP;
905906
int option_dissociate = 0;
907+
struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
906908
int option_filter_submodules = -1; /* unspecified */
907909
struct string_list server_options = STRING_LIST_INIT_NODUP;
908910
const char *bundle_uri = NULL;
@@ -999,6 +1001,8 @@ int cmd_clone(int argc,
9991001
NULL
10001002
};
10011003

1004+
filter_options.allow_auto_filter = 1;
1005+
10021006
packet_trace_identity("clone");
10031007

10041008
repo_config(the_repository, git_clone_config, NULL);
@@ -1620,9 +1624,13 @@ int cmd_clone(int argc,
16201624
return 1;
16211625

16221626
junk_mode = JUNK_LEAVE_REPO;
1623-
err = checkout(submodule_progress, filter_submodules,
1627+
err = checkout(submodule_progress,
1628+
&filter_options,
1629+
filter_submodules,
16241630
ref_storage_format);
16251631

1632+
list_objects_filter_release(&filter_options);
1633+
16261634
string_list_clear(&option_not, 0);
16271635
string_list_clear(&option_config, 0);
16281636
string_list_clear(&server_options, 0);

0 commit comments

Comments
 (0)