fetch: inherit filter-spec from partial clone
Teach (partial) fetch to inherit the filter-spec used by the partial clone. Extend --no-filter to override this inheritance. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff Hostetler committed
Dec 8, 2017 at 15:58 UTC
aa57b871dad3cca07abead9a8d1fefceffe7578d
6 files changed
+89
-7
builtin/fetch-pack.c
+1
-1
@@ -158,7 +158,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
158
continue;
159
}
160
if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
161
- list_objects_filter_release(&args.filter_options);
161
+ list_objects_filter_set_no_filter(&args.filter_options);
162
continue;
163
}
164
usage(fetch_pack_usage);
builtin/fetch.c
+53
-3
@@ -1275,6 +1275,56 @@ static int fetch_multiple(struct string_list *list)
1275
return result;
1276
}
1277
1278
+/*
1279
+ * Fetching from the promisor remote should use the given filter-spec
1280
+ * or inherit the default filter-spec from the config.
1281
+ */
1282
+static inline void fetch_one_setup_partial(struct remote *remote)
1283
+{
1284
+ /*
1285
+ * Explicit --no-filter argument overrides everything, regardless
1286
+ * of any prior partial clones and fetches.
1287
+ */
1288
+ if (filter_options.no_filter)
1289
+ return;
1290
+
1291
+ /*
1292
+ * If no prior partial clone/fetch and the current fetch DID NOT
1293
+ * request a partial-fetch, do a normal fetch.
1294
+ */
1295
+ if (!repository_format_partial_clone && !filter_options.choice)
1296
+ return;
1297
+
1298
+ /*
1299
+ * If this is the FIRST partial-fetch request, we enable partial
1300
+ * on this repo and remember the given filter-spec as the default
1301
+ * for subsequent fetches to this remote.
1302
+ */
1303
+ if (!repository_format_partial_clone && filter_options.choice) {
1304
+ partial_clone_register(remote->name, &filter_options);
1305
+ return;
1306
+ }
1307
+
1308
+ /*
1309
+ * We are currently limited to only ONE promisor remote and only
1310
+ * allow partial-fetches from the promisor remote.
1311
+ */
1312
+ if (strcmp(remote->name, repository_format_partial_clone)) {
1313
+ if (filter_options.choice)
1314
+ die(_("--filter can only be used with the remote configured in core.partialClone"));
1315
+ return;
1316
+ }
1317
+
1318
+ /*
1319
+ * Do a partial-fetch from the promisor remote using either the
1320
+ * explicitly given filter-spec or inherit the filter-spec from
1321
+ * the config.
1322
+ */
1323
+ if (!filter_options.choice)
1324
+ partial_clone_get_default_filter_spec(&filter_options);
1325
+ return;
1326
+}
1327
+
1328
static int fetch_one(struct remote *remote, int argc, const char **argv)
1329
{
1330
static const char **refs = NULL;
@@ -1404,13 +1454,13 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
1454
}
1455
1456
if (remote) {
1407
- if (filter_options.choice &&
1408
- strcmp(remote->name, repository_format_partial_clone))
1409
- die(_("--filter can only be used with the remote configured in core.partialClone"));
1457
+ if (filter_options.choice || repository_format_partial_clone)
1458
+ fetch_one_setup_partial(remote);
1459
result = fetch_one(remote, argc, argv);
1460
} else {
1461
if (filter_options.choice)
1462
die(_("--filter can only be used with the remote configured in core.partialClone"));
1463
+ /* TODO should this also die if we have a previous partial-clone? */
1464
result = fetch_multiple(&list);
1465
}
1466
builtin/rev-list.c
+1
-1
@@ -460,7 +460,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
460
continue;
461
}
462
if (!strcmp(arg, ("--no-" CL_ARG__FILTER))) {
463
- list_objects_filter_release(&filter_options);
463
+ list_objects_filter_set_no_filter(&filter_options);
464
continue;
465
}
466
if (!strcmp(arg, "--filter-print-omitted")) {
list-objects-filter-options.c
+1
-1
@@ -94,7 +94,7 @@ int opt_parse_list_objects_filter(const struct option *opt,
94
struct list_objects_filter_options *filter_options = opt->value;
95
96
if (unset || !arg) {
97
- list_objects_filter_release(filter_options);
97
+ list_objects_filter_set_no_filter(filter_options);
98
return 0;
99
}
100
list-objects-filter-options.h
+12
@@ -30,6 +30,11 @@ struct list_objects_filter_options {
30
*/
31
enum list_objects_filter_choice choice;
32
33
+ /*
34
+ * Choice is LOFC_DISABLED because "--no-filter" was requested.
35
+ */
36
+ unsigned int no_filter : 1;
37
+
38
/*
39
* Parsed values (fields) from within the filter-spec. These are
40
* choice-specific; not all values will be defined for any given
@@ -58,6 +63,13 @@ int opt_parse_list_objects_filter(const struct option *opt,
63
void list_objects_filter_release(
64
struct list_objects_filter_options *filter_options);
65
66
+static inline void list_objects_filter_set_no_filter(
67
+ struct list_objects_filter_options *filter_options)
68
+{
69
+ list_objects_filter_release(filter_options);
70
+ filter_options->no_filter = 1;
71
+}
72
+
73
void partial_clone_register(
74
const char *remote,
75
const struct list_objects_filter_options *filter_options);
t/t5616-partial-clone.sh
+21
-1
@@ -59,7 +59,7 @@ test_expect_success 'push new commits to server' '
59
git -C src remote add srv "file://$(pwd)/srv.bare" &&
60
for x in a b c d e
61
do
62
- echo "Mod $x" >>src/file.1.txt
62
+ echo "Mod file.1.txt $x" >>src/file.1.txt
63
git -C src add file.1.txt
64
git -C src commit -m "mod $x"
65
done &&
@@ -93,4 +93,24 @@ test_expect_success 'verify blame causes dynamic object fetch' '
93
test_line_count = 0 observed
94
'
95
96
+# create new commits in "src" repo to establish a history on file.2.txt
97
+# and push to "srv.bare".
98
+test_expect_success 'push new commits to server for file.2.txt' '
99
+ for x in a b c d e f
100
+ do
101
+ echo "Mod file.2.txt $x" >>src/file.2.txt
102
+ git -C src add file.2.txt
103
+ git -C src commit -m "mod $x"
104
+ done &&
105
+ git -C src push -u srv master
106
+'
107
+
108
+# Do FULL fetch by disabling filter-spec using --no-filter.
109
+# Verify we have all the new blobs.
110
+test_expect_success 'override inherited filter-spec using --no-filter' '
111
+ git -C pc1 fetch --no-filter origin &&
112
+ git -C pc1 rev-list master..origin/master --quiet --objects --missing=print >observed &&
113
+ test_line_count = 0 observed
114
+'
115
+
116
test_done