]> git.ipfire.org Git - thirdparty/git.git/commitdiff
rev-list: allow filtering of provided items
authorPatrick Steinhardt <ps@pks.im>
Mon, 19 Apr 2021 11:47:06 +0000 (13:47 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 19 Apr 2021 21:09:11 +0000 (14:09 -0700)
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>
Documentation/rev-list-options.txt
builtin/pack-objects.c
builtin/rev-list.c
pack-bitmap.c
pack-bitmap.h
reachable.c
t/t6112-rev-list-filters-objects.sh
t/t6113-rev-list-bitmap-filters.sh

index 3afa8fffbdf0900223c26dd3d61c66ba5acbc717..5bf2a85f69da26c9aef033b98b73be4215e2e6e3 100644 (file)
@@ -933,6 +933,11 @@ equivalent.
 --no-filter::
        Turn off any previous `--filter=` argument.
 
+--filter-provided-objects::
+       Filter the list of explicitly provided objects, which would otherwise
+       always be printed even if they did not match any of the filters. Only
+       useful with `--filter=`.
+
 --filter-print-omitted::
        Only useful with `--filter=`; prints a list of the objects omitted
        by the filter.  Object IDs are prefixed with a ``~'' character.
index 525c2d85529f41bc56fb3495f9f7e9dec9557c81..2f2026dc87f883d2829762c6ee86f9ae906e8083 100644 (file)
@@ -3516,7 +3516,7 @@ static int pack_options_allow_reuse(void)
 
 static int get_object_list_from_bitmap(struct rev_info *revs)
 {
-       if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options)))
+       if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options, 0)))
                return -1;
 
        if (pack_options_allow_reuse() &&
index b4d8ea0a35b5b2a0fde7302312b3bf39a5edcda1..7677b1af5a45fcaf6df9afd00660e98081c68bd8 100644 (file)
@@ -398,7 +398,8 @@ static inline int parse_missing_action_value(const char *value)
 }
 
 static int try_bitmap_count(struct rev_info *revs,
-                           struct list_objects_filter_options *filter)
+                           struct list_objects_filter_options *filter,
+                           int filter_provided_objects)
 {
        uint32_t commit_count = 0,
                 tag_count = 0,
@@ -433,7 +434,7 @@ static int try_bitmap_count(struct rev_info *revs,
         */
        max_count = revs->max_count;
 
-       bitmap_git = prepare_bitmap_walk(revs, filter);
+       bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
        if (!bitmap_git)
                return -1;
 
@@ -450,7 +451,8 @@ static int try_bitmap_count(struct rev_info *revs,
 }
 
 static int try_bitmap_traversal(struct rev_info *revs,
-                               struct list_objects_filter_options *filter)
+                               struct list_objects_filter_options *filter,
+                               int filter_provided_objects)
 {
        struct bitmap_index *bitmap_git;
 
@@ -461,7 +463,7 @@ static int try_bitmap_traversal(struct rev_info *revs,
        if (revs->max_count >= 0)
                return -1;
 
-       bitmap_git = prepare_bitmap_walk(revs, filter);
+       bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
        if (!bitmap_git)
                return -1;
 
@@ -471,14 +473,15 @@ static int try_bitmap_traversal(struct rev_info *revs,
 }
 
 static int try_bitmap_disk_usage(struct rev_info *revs,
-                                struct list_objects_filter_options *filter)
+                                struct list_objects_filter_options *filter,
+                                int filter_provided_objects)
 {
        struct bitmap_index *bitmap_git;
 
        if (!show_disk_usage)
                return -1;
 
-       bitmap_git = prepare_bitmap_walk(revs, filter);
+       bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
        if (!bitmap_git)
                return -1;
 
@@ -499,6 +502,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
        int bisect_show_vars = 0;
        int bisect_find_all = 0;
        int use_bitmap_index = 0;
+       int filter_provided_objects = 0;
        const char *show_progress = NULL;
 
        if (argc == 2 && !strcmp(argv[1], "-h"))
@@ -599,6 +603,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
                        list_objects_filter_set_no_filter(&filter_options);
                        continue;
                }
+               if (!strcmp(arg, "--filter-provided-objects")) {
+                       filter_provided_objects = 1;
+                       continue;
+               }
                if (!strcmp(arg, "--filter-print-omitted")) {
                        arg_print_omitted = 1;
                        continue;
@@ -665,11 +673,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
                progress = start_delayed_progress(show_progress, 0);
 
        if (use_bitmap_index) {
-               if (!try_bitmap_count(&revs, &filter_options))
+               if (!try_bitmap_count(&revs, &filter_options, filter_provided_objects))
                        return 0;
-               if (!try_bitmap_disk_usage(&revs, &filter_options))
+               if (!try_bitmap_disk_usage(&revs, &filter_options, filter_provided_objects))
                        return 0;
-               if (!try_bitmap_traversal(&revs, &filter_options))
+               if (!try_bitmap_traversal(&revs, &filter_options, filter_provided_objects))
                        return 0;
        }
 
@@ -694,6 +702,16 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
                        return show_bisect_vars(&info, reaches, all);
        }
 
+       if (filter_provided_objects) {
+               struct commit_list *c;
+               for (i = 0; i < revs.pending.nr; i++) {
+                       struct object_array_entry *pending = revs.pending.objects + i;
+                       pending->item->flags |= NOT_USER_GIVEN;
+               }
+               for (c = revs.commits; c; c = c->next)
+                       c->item->object.flags |= NOT_USER_GIVEN;
+       }
+
        if (arg_print_omitted)
                oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
        if (arg_missing_action == MA_PRINT)
index 7ce3ede7e478c8937888e7c8b712947cca40d46a..6b790a834b2ea6deef10b52d0ae46daf39f7763c 100644 (file)
@@ -986,7 +986,8 @@ static int can_filter_bitmap(struct list_objects_filter_options *filter)
 }
 
 struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
-                                        struct list_objects_filter_options *filter)
+                                        struct list_objects_filter_options *filter,
+                                        int filter_provided_objects)
 {
        unsigned int i;
 
@@ -1081,7 +1082,8 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
        if (haves_bitmap)
                bitmap_and_not(wants_bitmap, haves_bitmap);
 
-       filter_bitmap(bitmap_git, wants, wants_bitmap, filter);
+       filter_bitmap(bitmap_git, (filter && filter_provided_objects) ? NULL : wants,
+                     wants_bitmap, filter);
 
        bitmap_git->result = wants_bitmap;
        bitmap_git->haves = haves_bitmap;
index 36d99930d8d5288a7367235eba8d533ed8f76f99..bb45217d3b660647871d4516b3253c015453dee5 100644 (file)
@@ -50,7 +50,8 @@ void traverse_bitmap_commit_list(struct bitmap_index *,
                                 show_reachable_fn show_reachable);
 void test_bitmap_walk(struct rev_info *revs);
 struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
-                                        struct list_objects_filter_options *filter);
+                                        struct list_objects_filter_options *filter,
+                                        int filter_provided_objects);
 int reuse_partial_packfile_from_bitmap(struct bitmap_index *,
                                       struct packed_git **packfile,
                                       uint32_t *entries,
index 77a60c70a5db775d2f783023eeb757c1eb61d8a4..fc833cae43b2c98420b49c8b62fd7e39b7b11ca2 100644 (file)
@@ -223,7 +223,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
        cp.progress = progress;
        cp.count = 0;
 
-       bitmap_git = prepare_bitmap_walk(revs, NULL);
+       bitmap_git = prepare_bitmap_walk(revs, NULL, 0);
        if (bitmap_git) {
                traverse_bitmap_commit_list(bitmap_git, revs, mark_object_seen);
                free_bitmap_index(bitmap_git);
index c810a6280741441d0a7b88c18081aed0f199ffa4..4ade105db385c3458d4549d596923bb4197c605d 100755 (executable)
@@ -203,6 +203,34 @@ test_expect_success 'verify object:type=tag prints tag' '
        test_cmp expected actual
 '
 
+test_expect_success 'verify object:type=blob prints only blob with --filter-provided-objects' '
+       printf "%s blob\n" $(git -C object-type rev-parse HEAD:blob) >expected &&
+       git -C object-type rev-list --objects \
+               --filter=object:type=blob --filter-provided-objects HEAD >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'verify object:type=tree prints only tree with --filter-provided-objects' '
+       printf "%s \n" $(git -C object-type rev-parse HEAD^{tree}) >expected &&
+       git -C object-type rev-list --objects \
+               --filter=object:type=tree HEAD --filter-provided-objects >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'verify object:type=commit prints only commit with --filter-provided-objects' '
+       git -C object-type rev-parse HEAD >expected &&
+       git -C object-type rev-list --objects \
+               --filter=object:type=commit --filter-provided-objects HEAD >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'verify object:type=tag prints only tag with --filter-provided-objects' '
+       printf "%s tag\n" $(git -C object-type rev-parse tag) >expected &&
+       git -C object-type rev-list --objects \
+               --filter=object:type=tag --filter-provided-objects tag >actual &&
+       test_cmp expected actual
+'
+
 # Test sparse:path=<path> filter.
 # !!!!
 # NOTE: sparse:path filter support has been dropped for security reasons,
index cb9db7df6f1c7935a51dbcbdc00adf1304dffe3a..4d8e09167e78d078a6c14e7d51e3a9cb0aa7bf89 100755 (executable)
@@ -98,6 +98,28 @@ test_expect_success 'object:type filter' '
        test_bitmap_traversal expect actual
 '
 
+test_expect_success 'object:type filter with --filter-provided-objects' '
+       git rev-list --objects --filter-provided-objects --filter=object:type=tag tag >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter-provided-objects --filter=object:type=tag tag >actual &&
+       test_cmp expect actual &&
+
+       git rev-list --objects --filter-provided-objects --filter=object:type=commit tag >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter-provided-objects --filter=object:type=commit tag >actual &&
+       test_bitmap_traversal expect actual &&
+
+       git rev-list --objects --filter-provided-objects --filter=object:type=tree tag >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter-provided-objects --filter=object:type=tree tag >actual &&
+       test_bitmap_traversal expect actual &&
+
+       git rev-list --objects --filter-provided-objects --filter=object:type=blob tag >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter-provided-objects --filter=object:type=blob tag >actual &&
+       test_bitmap_traversal expect actual
+'
+
 test_expect_success 'combine filter' '
        git rev-list --objects --filter=blob:limit=1000 --filter=object:type=blob tag >expect &&
        git rev-list --use-bitmap-index \
@@ -105,4 +127,18 @@ test_expect_success 'combine filter' '
        test_bitmap_traversal expect actual
 '
 
+test_expect_success 'combine filter with --filter-provided-objects' '
+       git rev-list --objects --filter-provided-objects --filter=blob:limit=1000 --filter=object:type=blob tag >expect &&
+       git rev-list --use-bitmap-index \
+                    --objects --filter-provided-objects --filter=blob:limit=1000 --filter=object:type=blob tag >actual &&
+       test_bitmap_traversal expect actual &&
+
+       git cat-file --batch-check="%(objecttype) %(objectsize)" <actual >objects &&
+       while read objecttype objectsize
+       do
+               test "$objecttype" = blob || return 1
+               test "$objectsize" -le 1000 || return 1
+       done <objects
+'
+
 test_done