rev-list: allow filtering of provided items
When providing an object filter, it is currently impossible to also filter provided items. E.g. when executing `git rev-list HEAD` , the commit this reference points to will be treated as user-provided and is thus excluded from the filtering mechanism. This makes it harder than necessary to properly use the new `--filter=object:type` filter given that even if the user wants to only see blobs, he'll still see commits of provided references. Improve this by introducing a new `--filter-provided-objects` option to the git-rev-parse(1) command. If given, then all user-provided references will be subject to filtering. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Apr 19, 2021 at 13:47 UTC
9cf68b27d50c29a0370bd61581d350b0b0a18e85
8 files changed
+104
-14
Documentation/rev-list-options.txt
+5
@@ -933,6 +933,11 @@ equivalent.
933
--no-filter::
934
Turn off any previous `--filter=` argument.
935
936
+--filter-provided-objects::
937
+ Filter the list of explicitly provided objects, which would otherwise
938
+ always be printed even if they did not match any of the filters. Only
939
+ useful with `--filter=`.
940
+
941
--filter-print-omitted::
942
Only useful with `--filter=`; prints a list of the objects omitted
943
by the filter. Object IDs are prefixed with a ``~'' character.
builtin/pack-objects.c
+1
-1
@@ -3516,7 +3516,7 @@ static int pack_options_allow_reuse(void)
3516
3517
static int get_object_list_from_bitmap(struct rev_info *revs)
3518
{
3519
- if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options)))
3519
+ if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options, 0)))
3520
return -1;
3521
3522
if (pack_options_allow_reuse() &&
builtin/rev-list.c
+27
-9
@@ -398,7 +398,8 @@ static inline int parse_missing_action_value(const char *value)
398
}
399
400
static int try_bitmap_count(struct rev_info *revs,
401
- struct list_objects_filter_options *filter)
401
+ struct list_objects_filter_options *filter,
402
+ int filter_provided_objects)
403
{
404
uint32_t commit_count = 0,
405
tag_count = 0,
@@ -433,7 +434,7 @@ static int try_bitmap_count(struct rev_info *revs,
434
*/
435
max_count = revs->max_count;
436
436
- bitmap_git = prepare_bitmap_walk(revs, filter);
437
+ bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
438
if (!bitmap_git)
439
return -1;
440
@@ -450,7 +451,8 @@ static int try_bitmap_count(struct rev_info *revs,
451
}
452
453
static int try_bitmap_traversal(struct rev_info *revs,
453
- struct list_objects_filter_options *filter)
454
+ struct list_objects_filter_options *filter,
455
+ int filter_provided_objects)
456
{
457
struct bitmap_index *bitmap_git;
458
@@ -461,7 +463,7 @@ static int try_bitmap_traversal(struct rev_info *revs,
463
if (revs->max_count >= 0)
464
return -1;
465
464
- bitmap_git = prepare_bitmap_walk(revs, filter);
466
+ bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
467
if (!bitmap_git)
468
return -1;
469
@@ -471,14 +473,15 @@ static int try_bitmap_traversal(struct rev_info *revs,
473
}
474
475
static int try_bitmap_disk_usage(struct rev_info *revs,
474
- struct list_objects_filter_options *filter)
476
+ struct list_objects_filter_options *filter,
477
+ int filter_provided_objects)
478
{
479
struct bitmap_index *bitmap_git;
480
481
if (!show_disk_usage)
482
return -1;
483
481
- bitmap_git = prepare_bitmap_walk(revs, filter);
484
+ bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
485
if (!bitmap_git)
486
return -1;
487
@@ -499,6 +502,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
502
int bisect_show_vars = 0;
503
int bisect_find_all = 0;
504
int use_bitmap_index = 0;
505
+ int filter_provided_objects = 0;
506
const char *show_progress = NULL;
507
508
if (argc == 2 && !strcmp(argv[1], "-h"))
@@ -599,6 +603,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
603
list_objects_filter_set_no_filter(&filter_options);
604
continue;
605
}
606
+ if (!strcmp(arg, "--filter-provided-objects")) {
607
+ filter_provided_objects = 1;
608
+ continue;
609
+ }
610
if (!strcmp(arg, "--filter-print-omitted")) {
611
arg_print_omitted = 1;
612
continue;
@@ -665,11 +673,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
673
progress = start_delayed_progress(show_progress, 0);
674
675
if (use_bitmap_index) {
668
- if (!try_bitmap_count(&revs, &filter_options))
676
+ if (!try_bitmap_count(&revs, &filter_options, filter_provided_objects))
677
return 0;
670
- if (!try_bitmap_disk_usage(&revs, &filter_options))
678
+ if (!try_bitmap_disk_usage(&revs, &filter_options, filter_provided_objects))
679
return 0;
672
- if (!try_bitmap_traversal(&revs, &filter_options))
680
+ if (!try_bitmap_traversal(&revs, &filter_options, filter_provided_objects))
681
return 0;
682
}
683
@@ -694,6 +702,16 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
702
return show_bisect_vars(&info, reaches, all);
703
}
704
705
+ if (filter_provided_objects) {
706
+ struct commit_list *c;
707
+ for (i = 0; i < revs.pending.nr; i++) {
708
+ struct object_array_entry *pending = revs.pending.objects + i;
709
+ pending->item->flags |= NOT_USER_GIVEN;
710
+ }
711
+ for (c = revs.commits; c; c = c->next)
712
+ c->item->object.flags |= NOT_USER_GIVEN;
713
+ }
714
+
715
if (arg_print_omitted)
716
oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
717
if (arg_missing_action == MA_PRINT)
pack-bitmap.c
+4
-2
@@ -986,7 +986,8 @@ static int can_filter_bitmap(struct list_objects_filter_options *filter)
986
}
987
988
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
989
- struct list_objects_filter_options *filter)
989
+ struct list_objects_filter_options *filter,
990
+ int filter_provided_objects)
991
{
992
unsigned int i;
993
@@ -1081,7 +1082,8 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
1082
if (haves_bitmap)
1083
bitmap_and_not(wants_bitmap, haves_bitmap);
1084
1084
- filter_bitmap(bitmap_git, wants, wants_bitmap, filter);
1085
+ filter_bitmap(bitmap_git, (filter && filter_provided_objects) ? NULL : wants,
1086
+ wants_bitmap, filter);
1087
1088
bitmap_git->result = wants_bitmap;
1089
bitmap_git->haves = haves_bitmap;
pack-bitmap.h
+2
-1
@@ -50,7 +50,8 @@ void traverse_bitmap_commit_list(struct bitmap_index *,
50
show_reachable_fn show_reachable);
51
void test_bitmap_walk(struct rev_info *revs);
52
struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
53
- struct list_objects_filter_options *filter);
53
+ struct list_objects_filter_options *filter,
54
+ int filter_provided_objects);
55
int reuse_partial_packfile_from_bitmap(struct bitmap_index *,
56
struct packed_git **packfile,
57
uint32_t *entries,
reachable.c
+1
-1
@@ -223,7 +223,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
223
cp.progress = progress;
224
cp.count = 0;
225
226
- bitmap_git = prepare_bitmap_walk(revs, NULL);
226
+ bitmap_git = prepare_bitmap_walk(revs, NULL, 0);
227
if (bitmap_git) {
228
traverse_bitmap_commit_list(bitmap_git, revs, mark_object_seen);
229
free_bitmap_index(bitmap_git);
t/t6112-rev-list-filters-objects.sh
+28
@@ -203,6 +203,34 @@ test_expect_success 'verify object:type=tag prints tag' '
203
test_cmp expected actual
204
'
205
206
+test_expect_success 'verify object:type=blob prints only blob with --filter-provided-objects' '
207
+ printf "%s blob\n" $(git -C object-type rev-parse HEAD:blob) >expected &&
208
+ git -C object-type rev-list --objects \
209
+ --filter=object:type=blob --filter-provided-objects HEAD >actual &&
210
+ test_cmp expected actual
211
+'
212
+
213
+test_expect_success 'verify object:type=tree prints only tree with --filter-provided-objects' '
214
+ printf "%s \n" $(git -C object-type rev-parse HEAD^{tree}) >expected &&
215
+ git -C object-type rev-list --objects \
216
+ --filter=object:type=tree HEAD --filter-provided-objects >actual &&
217
+ test_cmp expected actual
218
+'
219
+
220
+test_expect_success 'verify object:type=commit prints only commit with --filter-provided-objects' '
221
+ git -C object-type rev-parse HEAD >expected &&
222
+ git -C object-type rev-list --objects \
223
+ --filter=object:type=commit --filter-provided-objects HEAD >actual &&
224
+ test_cmp expected actual
225
+'
226
+
227
+test_expect_success 'verify object:type=tag prints only tag with --filter-provided-objects' '
228
+ printf "%s tag\n" $(git -C object-type rev-parse tag) >expected &&
229
+ git -C object-type rev-list --objects \
230
+ --filter=object:type=tag --filter-provided-objects tag >actual &&
231
+ test_cmp expected actual
232
+'
233
+
234
# Test sparse:path=<path> filter.
235
# !!!!
236
# NOTE: sparse:path filter support has been dropped for security reasons,
t/t6113-rev-list-bitmap-filters.sh
+36
@@ -98,6 +98,28 @@ test_expect_success 'object:type filter' '
98
test_bitmap_traversal expect actual
99
'
100
101
+test_expect_success 'object:type filter with --filter-provided-objects' '
102
+ git rev-list --objects --filter-provided-objects --filter=object:type=tag tag >expect &&
103
+ git rev-list --use-bitmap-index \
104
+ --objects --filter-provided-objects --filter=object:type=tag tag >actual &&
105
+ test_cmp expect actual &&
106
+
107
+ git rev-list --objects --filter-provided-objects --filter=object:type=commit tag >expect &&
108
+ git rev-list --use-bitmap-index \
109
+ --objects --filter-provided-objects --filter=object:type=commit tag >actual &&
110
+ test_bitmap_traversal expect actual &&
111
+
112
+ git rev-list --objects --filter-provided-objects --filter=object:type=tree tag >expect &&
113
+ git rev-list --use-bitmap-index \
114
+ --objects --filter-provided-objects --filter=object:type=tree tag >actual &&
115
+ test_bitmap_traversal expect actual &&
116
+
117
+ git rev-list --objects --filter-provided-objects --filter=object:type=blob tag >expect &&
118
+ git rev-list --use-bitmap-index \
119
+ --objects --filter-provided-objects --filter=object:type=blob tag >actual &&
120
+ test_bitmap_traversal expect actual
121
+'
122
+
123
test_expect_success 'combine filter' '
124
git rev-list --objects --filter=blob:limit=1000 --filter=object:type=blob tag >expect &&
125
git rev-list --use-bitmap-index \
@@ -105,4 +127,18 @@ test_expect_success 'combine filter' '
127
test_bitmap_traversal expect actual
128
'
129
130
+test_expect_success 'combine filter with --filter-provided-objects' '
131
+ git rev-list --objects --filter-provided-objects --filter=blob:limit=1000 --filter=object:type=blob tag >expect &&
132
+ git rev-list --use-bitmap-index \
133
+ --objects --filter-provided-objects --filter=blob:limit=1000 --filter=object:type=blob tag >actual &&
134
+ test_bitmap_traversal expect actual &&
135
+
136
+ git cat-file --batch-check="%(objecttype) %(objectsize)" <actual >objects &&
137
+ while read objecttype objectsize
138
+ do
139
+ test "$objecttype" = blob || return 1
140
+ test "$objectsize" -le 1000 || return 1
141
+ done <objects
142
+'
143
+
144
test_done