Skip to content

Commit e60c155

Browse files
chriscoolgitster
authored andcommitted
list-objects-filter-options: support 'auto' mode for --filter
In a following commit, we are going to allow passing "auto" as a <filterspec> to the `--filter=<filterspec>` option, but only for some commands. Other commands that support the `--filter=<filterspec>` option should still die() when 'auto' is passed. Let's set up the "list-objects-filter-options.{c,h}" infrastructure to support that: - Add a new `unsigned int allow_auto_filter : 1;` flag to `struct list_objects_filter_options` which specifies if "auto" is accepted or not by the current command. - Change gently_parse_list_objects_filter() to parse "auto" if it's accepted. - Make sure we die() if "auto" is combined with another filter. - Update list_objects_filter_release() to preserve the allow_auto_filter flag, as this function is often called (via opt_parse_list_objects_filter) to reset the struct before parsing a new value. Let's also update `list-objects-filter.c` to recognize the new `LOFC_AUTO` choice. Since "auto" must be resolved to a concrete filter before filtering actually begins, initializing a filter with `LOFC_AUTO` is invalid and will trigger a BUG(). Note that ideally combining "auto" with "auto" could be allowed, but in practice, it's probably not worth the added code complexity. And if we really want it, nothing prevents us to allow it in future work. If we ever want to give a meaning to combining "auto" with a different filter too, nothing prevents us to do that in future work either. Also note that the new `allow_auto_filter` flag depends on the command, not user choices, so it should be reset to the command default when `struct list_objects_filter_options` instances are reset. While at it, let's add a new "u-list-objects-filter-options.c" file for `struct list_objects_filter_options` related unit tests. For now it only tests gently_parse_list_objects_filter() though. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 349c8a5 commit e60c155

6 files changed

Lines changed: 103 additions & 3 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,7 @@ CLAR_TEST_SUITES += u-dir
15181518
CLAR_TEST_SUITES += u-example-decorate
15191519
CLAR_TEST_SUITES += u-hash
15201520
CLAR_TEST_SUITES += u-hashmap
1521+
CLAR_TEST_SUITES += u-list-objects-filter-options
15211522
CLAR_TEST_SUITES += u-mem-pool
15221523
CLAR_TEST_SUITES += u-oid-array
15231524
CLAR_TEST_SUITES += u-oidmap

list-objects-filter-options.c

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ const char *list_object_filter_config_name(enum list_objects_filter_choice c)
2020
case LOFC_DISABLED:
2121
/* we have no name for "no filter at all" */
2222
break;
23+
case LOFC_AUTO:
24+
return "auto";
2325
case LOFC_BLOB_NONE:
2426
return "blob:none";
2527
case LOFC_BLOB_LIMIT:
@@ -52,7 +54,16 @@ int gently_parse_list_objects_filter(
5254
if (filter_options->choice)
5355
BUG("filter_options already populated");
5456

55-
if (!strcmp(arg, "blob:none")) {
57+
if (!strcmp(arg, "auto")) {
58+
if (!filter_options->allow_auto_filter) {
59+
strbuf_addstr(errbuf,
60+
_("'auto' filter not supported by this command"));
61+
return 1;
62+
}
63+
filter_options->choice = LOFC_AUTO;
64+
return 0;
65+
66+
} else if (!strcmp(arg, "blob:none")) {
5667
filter_options->choice = LOFC_BLOB_NONE;
5768
return 0;
5869

@@ -146,10 +157,22 @@ static int parse_combine_subfilter(
146157

147158
decoded = url_percent_decode(subspec->buf);
148159

149-
result = has_reserved_character(subspec, errbuf) ||
150-
gently_parse_list_objects_filter(
160+
result = has_reserved_character(subspec, errbuf);
161+
if (result)
162+
goto cleanup;
163+
164+
result = gently_parse_list_objects_filter(
151165
&filter_options->sub[new_index], decoded, errbuf);
166+
if (result)
167+
goto cleanup;
168+
169+
result = (filter_options->sub[new_index].choice == LOFC_AUTO);
170+
if (result) {
171+
strbuf_addstr(errbuf, _("an 'auto' filter cannot be combined"));
172+
goto cleanup;
173+
}
152174

175+
cleanup:
153176
free(decoded);
154177
return result;
155178
}
@@ -263,6 +286,9 @@ void parse_list_objects_filter(
263286
} else {
264287
struct list_objects_filter_options *sub;
265288

289+
if (filter_options->choice == LOFC_AUTO)
290+
die(_("an 'auto' filter is incompatible with any other filter"));
291+
266292
/*
267293
* Make filter_options an LOFC_COMBINE spec so we can trivially
268294
* add subspecs to it.
@@ -277,6 +303,9 @@ void parse_list_objects_filter(
277303
if (gently_parse_list_objects_filter(sub, arg, &errbuf))
278304
die("%s", errbuf.buf);
279305

306+
if (sub->choice == LOFC_AUTO)
307+
die(_("an 'auto' filter is incompatible with any other filter"));
308+
280309
strbuf_addch(&filter_options->filter_spec, '+');
281310
filter_spec_append_urlencode(filter_options, arg);
282311
}
@@ -317,6 +346,7 @@ void list_objects_filter_release(
317346
struct list_objects_filter_options *filter_options)
318347
{
319348
size_t sub;
349+
unsigned int allow_auto_filter = filter_options->allow_auto_filter;
320350

321351
if (!filter_options)
322352
return;
@@ -326,6 +356,7 @@ void list_objects_filter_release(
326356
list_objects_filter_release(&filter_options->sub[sub]);
327357
free(filter_options->sub);
328358
list_objects_filter_init(filter_options);
359+
filter_options->allow_auto_filter = allow_auto_filter;
329360
}
330361

331362
void partial_clone_register(

list-objects-filter-options.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum list_objects_filter_choice {
1818
LOFC_SPARSE_OID,
1919
LOFC_OBJECT_TYPE,
2020
LOFC_COMBINE,
21+
LOFC_AUTO,
2122
LOFC__COUNT /* must be last */
2223
};
2324

@@ -50,6 +51,11 @@ struct list_objects_filter_options {
5051
*/
5152
unsigned int no_filter : 1;
5253

54+
/*
55+
* Is LOFC_AUTO a valid option?
56+
*/
57+
unsigned int allow_auto_filter : 1;
58+
5359
/*
5460
* BEGIN choice-specific parsed values from within the filter-spec. Only
5561
* some values will be defined for any given choice.

list-objects-filter.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,13 @@ static void filter_combine__init(
745745
filter->finalize_omits_fn = filter_combine__finalize_omits;
746746
}
747747

748+
static void filter_auto__init(
749+
struct list_objects_filter_options *filter_options UNUSED,
750+
struct filter *filter UNUSED)
751+
{
752+
BUG("LOFC_AUTO should have been resolved before initializing the filter");
753+
}
754+
748755
typedef void (*filter_init_fn)(
749756
struct list_objects_filter_options *filter_options,
750757
struct filter *filter);
@@ -760,6 +767,7 @@ static filter_init_fn s_filters[] = {
760767
filter_sparse_oid__init,
761768
filter_object_type__init,
762769
filter_combine__init,
770+
filter_auto__init,
763771
};
764772

765773
struct filter *list_objects_filter__init(

t/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ clar_test_suites = [
44
'unit-tests/u-example-decorate.c',
55
'unit-tests/u-hash.c',
66
'unit-tests/u-hashmap.c',
7+
'unit-tests/u-list-objects-filter-options.c',
78
'unit-tests/u-mem-pool.c',
89
'unit-tests/u-oid-array.c',
910
'unit-tests/u-oidmap.c',
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "unit-test.h"
2+
#include "list-objects-filter-options.h"
3+
#include "strbuf.h"
4+
5+
/* Helper to test gently_parse_list_objects_filter() */
6+
static void check_gentle_parse(const char *filter_spec,
7+
int expect_success,
8+
int allow_auto,
9+
enum list_objects_filter_choice expected_choice)
10+
{
11+
struct list_objects_filter_options filter_options = LIST_OBJECTS_FILTER_INIT;
12+
struct strbuf errbuf = STRBUF_INIT;
13+
int ret;
14+
15+
filter_options.allow_auto_filter = allow_auto;
16+
17+
ret = gently_parse_list_objects_filter(&filter_options, filter_spec, &errbuf);
18+
19+
if (expect_success) {
20+
cl_assert_equal_i(ret, 0);
21+
cl_assert_equal_i(expected_choice, filter_options.choice);
22+
cl_assert_equal_i(errbuf.len, 0);
23+
} else {
24+
cl_assert(ret != 0);
25+
cl_assert(errbuf.len > 0);
26+
}
27+
28+
strbuf_release(&errbuf);
29+
list_objects_filter_release(&filter_options);
30+
}
31+
32+
void test_list_objects_filter_options__regular_filters(void)
33+
{
34+
check_gentle_parse("blob:none", 1, 0, LOFC_BLOB_NONE);
35+
check_gentle_parse("blob:none", 1, 1, LOFC_BLOB_NONE);
36+
check_gentle_parse("blob:limit=5k", 1, 0, LOFC_BLOB_LIMIT);
37+
check_gentle_parse("blob:limit=5k", 1, 1, LOFC_BLOB_LIMIT);
38+
check_gentle_parse("combine:blob:none+tree:0", 1, 0, LOFC_COMBINE);
39+
check_gentle_parse("combine:blob:none+tree:0", 1, 1, LOFC_COMBINE);
40+
}
41+
42+
void test_list_objects_filter_options__auto_allowed(void)
43+
{
44+
check_gentle_parse("auto", 1, 1, LOFC_AUTO);
45+
check_gentle_parse("auto", 0, 0, 0);
46+
}
47+
48+
void test_list_objects_filter_options__combine_auto_fails(void)
49+
{
50+
check_gentle_parse("combine:auto+blob:none", 0, 1, 0);
51+
check_gentle_parse("combine:blob:none+auto", 0, 1, 0);
52+
check_gentle_parse("combine:auto+auto", 0, 1, 0);
53+
}

0 commit comments

Comments
 (0)