Skip to content

Commit 8585d6c

Browse files
committed
Merge branch 'ps/rev-list-object-type-filter'
"git rev-list" learns the "--filter=object:type=<type>" option, which can be used to exclude objects of the given kind from the packfile generated by pack-objects. * ps/rev-list-object-type-filter: rev-list: allow filtering of provided items pack-bitmap: implement combined filter pack-bitmap: implement object type filter list-objects: implement object type filter list-objects: support filtering by tag and commit list-objects: move tag processing into its own function revision: mark commit parents as NOT_USER_GIVEN uploadpack.txt: document implication of `uploadpackfilter.allow`
2 parents 826ef0e + 9cf68b2 commit 8585d6c

16 files changed

+388
-30
lines changed

Documentation/config/uploadpack.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,16 @@ uploadpack.allowFilter::
5959

6060
uploadpackfilter.allow::
6161
Provides a default value for unspecified object filters (see: the
62-
below configuration variable).
62+
below configuration variable). If set to `true`, this will also
63+
enable all filters which get added in the future.
6364
Defaults to `true`.
6465

6566
uploadpackfilter.<filter>.allow::
6667
Explicitly allow or ban the object filter corresponding to
6768
`<filter>`, where `<filter>` may be one of: `blob:none`,
68-
`blob:limit`, `tree`, `sparse:oid`, or `combine`. If using
69-
combined filters, both `combine` and all of the nested filter
70-
kinds must be allowed. Defaults to `uploadpackfilter.allow`.
69+
`blob:limit`, `object:type`, `tree`, `sparse:oid`, or `combine`.
70+
If using combined filters, both `combine` and all of the nested
71+
filter kinds must be allowed. Defaults to `uploadpackfilter.allow`.
7172

7273
uploadpackfilter.tree.maxDepth::
7374
Only allow `--filter=tree:<n>` when `<n>` is no more than the value of

Documentation/rev-list-options.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,9 @@ or units. n may be zero. The suffixes k, m, and g can be used to name
892892
units in KiB, MiB, or GiB. For example, 'blob:limit=1k' is the same
893893
as 'blob:limit=1024'.
894894
+
895+
The form '--filter=object:type=(tag|commit|tree|blob)' omits all objects
896+
which are not of the requested type.
897+
+
895898
The form '--filter=sparse:oid=<blob-ish>' uses a sparse-checkout
896899
specification contained in the blob (or blob-expression) '<blob-ish>'
897900
to omit blobs that would not be not required for a sparse checkout on
@@ -930,6 +933,11 @@ equivalent.
930933
--no-filter::
931934
Turn off any previous `--filter=` argument.
932935

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+
933941
--filter-print-omitted::
934942
Only useful with `--filter=`; prints a list of the objects omitted
935943
by the filter. Object IDs are prefixed with a ``~'' character.

builtin/pack-objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3516,7 +3516,7 @@ static int pack_options_allow_reuse(void)
35163516

35173517
static int get_object_list_from_bitmap(struct rev_info *revs)
35183518
{
3519-
if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options)))
3519+
if (!(bitmap_git = prepare_bitmap_walk(revs, &filter_options, 0)))
35203520
return -1;
35213521

35223522
if (pack_options_allow_reuse() &&

builtin/rev-list.c

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,8 @@ static inline int parse_missing_action_value(const char *value)
398398
}
399399

400400
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)
402403
{
403404
uint32_t commit_count = 0,
404405
tag_count = 0,
@@ -433,7 +434,7 @@ static int try_bitmap_count(struct rev_info *revs,
433434
*/
434435
max_count = revs->max_count;
435436

436-
bitmap_git = prepare_bitmap_walk(revs, filter);
437+
bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
437438
if (!bitmap_git)
438439
return -1;
439440

@@ -450,7 +451,8 @@ static int try_bitmap_count(struct rev_info *revs,
450451
}
451452

452453
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)
454456
{
455457
struct bitmap_index *bitmap_git;
456458

@@ -461,7 +463,7 @@ static int try_bitmap_traversal(struct rev_info *revs,
461463
if (revs->max_count >= 0)
462464
return -1;
463465

464-
bitmap_git = prepare_bitmap_walk(revs, filter);
466+
bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
465467
if (!bitmap_git)
466468
return -1;
467469

@@ -471,14 +473,15 @@ static int try_bitmap_traversal(struct rev_info *revs,
471473
}
472474

473475
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)
475478
{
476479
struct bitmap_index *bitmap_git;
477480

478481
if (!show_disk_usage)
479482
return -1;
480483

481-
bitmap_git = prepare_bitmap_walk(revs, filter);
484+
bitmap_git = prepare_bitmap_walk(revs, filter, filter_provided_objects);
482485
if (!bitmap_git)
483486
return -1;
484487

@@ -499,6 +502,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
499502
int bisect_show_vars = 0;
500503
int bisect_find_all = 0;
501504
int use_bitmap_index = 0;
505+
int filter_provided_objects = 0;
502506
const char *show_progress = NULL;
503507

504508
if (argc == 2 && !strcmp(argv[1], "-h"))
@@ -599,6 +603,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
599603
list_objects_filter_set_no_filter(&filter_options);
600604
continue;
601605
}
606+
if (!strcmp(arg, "--filter-provided-objects")) {
607+
filter_provided_objects = 1;
608+
continue;
609+
}
602610
if (!strcmp(arg, "--filter-print-omitted")) {
603611
arg_print_omitted = 1;
604612
continue;
@@ -665,11 +673,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
665673
progress = start_delayed_progress(show_progress, 0);
666674

667675
if (use_bitmap_index) {
668-
if (!try_bitmap_count(&revs, &filter_options))
676+
if (!try_bitmap_count(&revs, &filter_options, filter_provided_objects))
669677
return 0;
670-
if (!try_bitmap_disk_usage(&revs, &filter_options))
678+
if (!try_bitmap_disk_usage(&revs, &filter_options, filter_provided_objects))
671679
return 0;
672-
if (!try_bitmap_traversal(&revs, &filter_options))
680+
if (!try_bitmap_traversal(&revs, &filter_options, filter_provided_objects))
673681
return 0;
674682
}
675683

@@ -694,6 +702,16 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
694702
return show_bisect_vars(&info, reaches, all);
695703
}
696704

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+
697715
if (arg_print_omitted)
698716
oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
699717
if (arg_missing_action == MA_PRINT)

list-objects-filter-options.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ const char *list_object_filter_config_name(enum list_objects_filter_choice c)
2929
return "tree";
3030
case LOFC_SPARSE_OID:
3131
return "sparse:oid";
32+
case LOFC_OBJECT_TYPE:
33+
return "object:type";
3234
case LOFC_COMBINE:
3335
return "combine";
3436
case LOFC__COUNT:
@@ -97,6 +99,19 @@ static int gently_parse_list_objects_filter(
9799
}
98100
return 1;
99101

102+
} else if (skip_prefix(arg, "object:type=", &v0)) {
103+
int type = type_from_string_gently(v0, strlen(v0), 1);
104+
if (type < 0) {
105+
strbuf_addf(errbuf, _("'%s' for 'object:type=<type>' is"
106+
"not a valid object type"), v0);
107+
return 1;
108+
}
109+
110+
filter_options->object_type = type;
111+
filter_options->choice = LOFC_OBJECT_TYPE;
112+
113+
return 0;
114+
100115
} else if (skip_prefix(arg, "combine:", &v0)) {
101116
return parse_combine_filter(filter_options, v0, errbuf);
102117

list-objects-filter-options.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef LIST_OBJECTS_FILTER_OPTIONS_H
22
#define LIST_OBJECTS_FILTER_OPTIONS_H
33

4+
#include "cache.h"
45
#include "parse-options.h"
56
#include "string-list.h"
67

@@ -13,6 +14,7 @@ enum list_objects_filter_choice {
1314
LOFC_BLOB_LIMIT,
1415
LOFC_TREE_DEPTH,
1516
LOFC_SPARSE_OID,
17+
LOFC_OBJECT_TYPE,
1618
LOFC_COMBINE,
1719
LOFC__COUNT /* must be last */
1820
};
@@ -54,6 +56,7 @@ struct list_objects_filter_options {
5456
char *sparse_oid_name;
5557
unsigned long blob_limit_value;
5658
unsigned long tree_exclude_depth;
59+
enum object_type object_type;
5760

5861
/* LOFC_COMBINE values */
5962

list-objects-filter.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ static enum list_objects_filter_result filter_blobs_none(
8282
default:
8383
BUG("unknown filter_situation: %d", filter_situation);
8484

85+
case LOFS_TAG:
86+
assert(obj->type == OBJ_TAG);
87+
/* always include all tag objects */
88+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
89+
90+
case LOFS_COMMIT:
91+
assert(obj->type == OBJ_COMMIT);
92+
/* always include all commit objects */
93+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
94+
8595
case LOFS_BEGIN_TREE:
8696
assert(obj->type == OBJ_TREE);
8797
/* always include all tree objects */
@@ -173,6 +183,16 @@ static enum list_objects_filter_result filter_trees_depth(
173183
default:
174184
BUG("unknown filter_situation: %d", filter_situation);
175185

186+
case LOFS_TAG:
187+
assert(obj->type == OBJ_TAG);
188+
/* always include all tag objects */
189+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
190+
191+
case LOFS_COMMIT:
192+
assert(obj->type == OBJ_COMMIT);
193+
/* always include all commit objects */
194+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
195+
176196
case LOFS_END_TREE:
177197
assert(obj->type == OBJ_TREE);
178198
filter_data->current_depth--;
@@ -267,6 +287,16 @@ static enum list_objects_filter_result filter_blobs_limit(
267287
default:
268288
BUG("unknown filter_situation: %d", filter_situation);
269289

290+
case LOFS_TAG:
291+
assert(obj->type == OBJ_TAG);
292+
/* always include all tag objects */
293+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
294+
295+
case LOFS_COMMIT:
296+
assert(obj->type == OBJ_COMMIT);
297+
/* always include all commit objects */
298+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
299+
270300
case LOFS_BEGIN_TREE:
271301
assert(obj->type == OBJ_TREE);
272302
/* always include all tree objects */
@@ -371,6 +401,16 @@ static enum list_objects_filter_result filter_sparse(
371401
default:
372402
BUG("unknown filter_situation: %d", filter_situation);
373403

404+
case LOFS_TAG:
405+
assert(obj->type == OBJ_TAG);
406+
/* always include all tag objects */
407+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
408+
409+
case LOFS_COMMIT:
410+
assert(obj->type == OBJ_COMMIT);
411+
/* always include all commit objects */
412+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
413+
374414
case LOFS_BEGIN_TREE:
375415
assert(obj->type == OBJ_TREE);
376416
dtype = DT_DIR;
@@ -505,6 +545,81 @@ static void filter_sparse_oid__init(
505545
filter->free_fn = filter_sparse_free;
506546
}
507547

548+
/*
549+
* A filter for list-objects to omit large blobs.
550+
* And to OPTIONALLY collect a list of the omitted OIDs.
551+
*/
552+
struct filter_object_type_data {
553+
enum object_type object_type;
554+
};
555+
556+
static enum list_objects_filter_result filter_object_type(
557+
struct repository *r,
558+
enum list_objects_filter_situation filter_situation,
559+
struct object *obj,
560+
const char *pathname,
561+
const char *filename,
562+
struct oidset *omits,
563+
void *filter_data_)
564+
{
565+
struct filter_object_type_data *filter_data = filter_data_;
566+
567+
switch (filter_situation) {
568+
default:
569+
BUG("unknown filter_situation: %d", filter_situation);
570+
571+
case LOFS_TAG:
572+
assert(obj->type == OBJ_TAG);
573+
if (filter_data->object_type == OBJ_TAG)
574+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
575+
return LOFR_MARK_SEEN;
576+
577+
case LOFS_COMMIT:
578+
assert(obj->type == OBJ_COMMIT);
579+
if (filter_data->object_type == OBJ_COMMIT)
580+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
581+
return LOFR_MARK_SEEN;
582+
583+
case LOFS_BEGIN_TREE:
584+
assert(obj->type == OBJ_TREE);
585+
586+
/*
587+
* If we only want to show commits or tags, then there is no
588+
* need to walk down trees.
589+
*/
590+
if (filter_data->object_type == OBJ_COMMIT ||
591+
filter_data->object_type == OBJ_TAG)
592+
return LOFR_SKIP_TREE;
593+
594+
if (filter_data->object_type == OBJ_TREE)
595+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
596+
597+
return LOFR_MARK_SEEN;
598+
599+
case LOFS_BLOB:
600+
assert(obj->type == OBJ_BLOB);
601+
602+
if (filter_data->object_type == OBJ_BLOB)
603+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
604+
return LOFR_MARK_SEEN;
605+
606+
case LOFS_END_TREE:
607+
return LOFR_ZERO;
608+
}
609+
}
610+
611+
static void filter_object_type__init(
612+
struct list_objects_filter_options *filter_options,
613+
struct filter *filter)
614+
{
615+
struct filter_object_type_data *d = xcalloc(1, sizeof(*d));
616+
d->object_type = filter_options->object_type;
617+
618+
filter->filter_data = d;
619+
filter->filter_object_fn = filter_object_type;
620+
filter->free_fn = free;
621+
}
622+
508623
/* A filter which only shows objects shown by all sub-filters. */
509624
struct combine_filter_data {
510625
struct subfilter *sub;
@@ -651,6 +766,7 @@ static filter_init_fn s_filters[] = {
651766
filter_blobs_limit__init,
652767
filter_trees_depth__init,
653768
filter_sparse_oid__init,
769+
filter_object_type__init,
654770
filter_combine__init,
655771
};
656772

list-objects-filter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ enum list_objects_filter_result {
5555
};
5656

5757
enum list_objects_filter_situation {
58+
LOFS_COMMIT,
59+
LOFS_TAG,
5860
LOFS_BEGIN_TREE,
5961
LOFS_END_TREE,
6062
LOFS_BLOB

0 commit comments

Comments
 (0)