Skip to content

Commit 9430147

Browse files
matvoregitster
authored andcommitted
list-objects-filter: encapsulate filter components
Encapsulate filter_fn, filter_free_fn, and filter_data into their own opaque struct. Due to opaqueness, filter_fn and filter_free_fn can no longer be accessed directly by users. Currently, all usages of filter_fn are guarded by a necessary check: (obj->flags & NOT_USER_GIVEN) && filter_fn Take the opportunity to include this check into the new function list_objects_filter__filter_object(), so that we no longer need to write this check at every caller of the filter function. Also, the init functions in list-objects-filter.c no longer need to confusingly return the filter constituents in various places (filter_fn and filter_free_fn as out parameters, and filter_data as the function's return value); they can just initialize the "struct filter" passed in. Helped-by: Jeff Hostetler <[email protected]> Helped-by: Jonathan Tan <[email protected]> Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Matthew DeVore <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8dca754 commit 9430147

File tree

3 files changed

+113
-89
lines changed

3 files changed

+113
-89
lines changed

list-objects-filter.c

Lines changed: 75 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@
2626
*/
2727
#define FILTER_SHOWN_BUT_REVISIT (1<<21)
2828

29+
struct filter {
30+
enum list_objects_filter_result (*filter_object_fn)(
31+
struct repository *r,
32+
enum list_objects_filter_situation filter_situation,
33+
struct object *obj,
34+
const char *pathname,
35+
const char *filename,
36+
void *filter_data);
37+
38+
void (*free_fn)(void *filter_data);
39+
40+
void *filter_data;
41+
};
42+
2943
/*
3044
* A filter for list-objects to omit ALL blobs from the traversal.
3145
* And to OPTIONALLY collect a list of the omitted OIDs.
@@ -67,18 +81,17 @@ static enum list_objects_filter_result filter_blobs_none(
6781
}
6882
}
6983

70-
static void *filter_blobs_none__init(
84+
static void filter_blobs_none__init(
7185
struct oidset *omitted,
7286
struct list_objects_filter_options *filter_options,
73-
filter_object_fn *filter_fn,
74-
filter_free_fn *filter_free_fn)
87+
struct filter *filter)
7588
{
7689
struct filter_blobs_none_data *d = xcalloc(1, sizeof(*d));
7790
d->omits = omitted;
7891

79-
*filter_fn = filter_blobs_none;
80-
*filter_free_fn = free;
81-
return d;
92+
filter->filter_data = d;
93+
filter->filter_object_fn = filter_blobs_none;
94+
filter->free_fn = free;
8295
}
8396

8497
/*
@@ -201,21 +214,20 @@ static void filter_trees_free(void *filter_data) {
201214
free(d);
202215
}
203216

204-
static void *filter_trees_depth__init(
217+
static void filter_trees_depth__init(
205218
struct oidset *omitted,
206219
struct list_objects_filter_options *filter_options,
207-
filter_object_fn *filter_fn,
208-
filter_free_fn *filter_free_fn)
220+
struct filter *filter)
209221
{
210222
struct filter_trees_depth_data *d = xcalloc(1, sizeof(*d));
211223
d->omits = omitted;
212224
oidmap_init(&d->seen_at_depth, 0);
213225
d->exclude_depth = filter_options->tree_exclude_depth;
214226
d->current_depth = 0;
215227

216-
*filter_fn = filter_trees_depth;
217-
*filter_free_fn = filter_trees_free;
218-
return d;
228+
filter->filter_data = d;
229+
filter->filter_object_fn = filter_trees_depth;
230+
filter->free_fn = filter_trees_free;
219231
}
220232

221233
/*
@@ -281,19 +293,18 @@ static enum list_objects_filter_result filter_blobs_limit(
281293
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
282294
}
283295

284-
static void *filter_blobs_limit__init(
296+
static void filter_blobs_limit__init(
285297
struct oidset *omitted,
286298
struct list_objects_filter_options *filter_options,
287-
filter_object_fn *filter_fn,
288-
filter_free_fn *filter_free_fn)
299+
struct filter *filter)
289300
{
290301
struct filter_blobs_limit_data *d = xcalloc(1, sizeof(*d));
291302
d->omits = omitted;
292303
d->max_bytes = filter_options->blob_limit_value;
293304

294-
*filter_fn = filter_blobs_limit;
295-
*filter_free_fn = free;
296-
return d;
305+
filter->filter_data = d;
306+
filter->filter_object_fn = filter_blobs_limit;
307+
filter->free_fn = free;
297308
}
298309

299310
/*
@@ -456,11 +467,10 @@ static void filter_sparse_free(void *filter_data)
456467
free(d);
457468
}
458469

459-
static void *filter_sparse_oid__init(
470+
static void filter_sparse_oid__init(
460471
struct oidset *omitted,
461472
struct list_objects_filter_options *filter_options,
462-
filter_object_fn *filter_fn,
463-
filter_free_fn *filter_free_fn)
473+
struct filter *filter)
464474
{
465475
struct filter_sparse_data *d = xcalloc(1, sizeof(*d));
466476
d->omits = omitted;
@@ -473,16 +483,15 @@ static void *filter_sparse_oid__init(
473483
d->array_frame[d->nr].child_prov_omit = 0;
474484
d->nr++;
475485

476-
*filter_fn = filter_sparse;
477-
*filter_free_fn = filter_sparse_free;
478-
return d;
486+
filter->filter_data = d;
487+
filter->filter_object_fn = filter_sparse;
488+
filter->free_fn = filter_sparse_free;
479489
}
480490

481-
typedef void *(*filter_init_fn)(
491+
typedef void (*filter_init_fn)(
482492
struct oidset *omitted,
483493
struct list_objects_filter_options *filter_options,
484-
filter_object_fn *filter_fn,
485-
filter_free_fn *filter_free_fn);
494+
struct filter *filter);
486495

487496
/*
488497
* Must match "enum list_objects_filter_choice".
@@ -495,12 +504,11 @@ static filter_init_fn s_filters[] = {
495504
filter_sparse_oid__init,
496505
};
497506

498-
void *list_objects_filter__init(
507+
struct filter *list_objects_filter__init(
499508
struct oidset *omitted,
500-
struct list_objects_filter_options *filter_options,
501-
filter_object_fn *filter_fn,
502-
filter_free_fn *filter_free_fn)
509+
struct list_objects_filter_options *filter_options)
503510
{
511+
struct filter *filter;
504512
filter_init_fn init_fn;
505513

506514
assert((sizeof(s_filters) / sizeof(s_filters[0])) == LOFC__COUNT);
@@ -510,10 +518,40 @@ void *list_objects_filter__init(
510518
filter_options->choice);
511519

512520
init_fn = s_filters[filter_options->choice];
513-
if (init_fn)
514-
return init_fn(omitted, filter_options,
515-
filter_fn, filter_free_fn);
516-
*filter_fn = NULL;
517-
*filter_free_fn = NULL;
518-
return NULL;
521+
if (!init_fn)
522+
return NULL;
523+
524+
filter = xcalloc(1, sizeof(*filter));
525+
init_fn(omitted, filter_options, filter);
526+
return filter;
527+
}
528+
529+
enum list_objects_filter_result list_objects_filter__filter_object(
530+
struct repository *r,
531+
enum list_objects_filter_situation filter_situation,
532+
struct object *obj,
533+
const char *pathname,
534+
const char *filename,
535+
struct filter *filter)
536+
{
537+
if (filter && (obj->flags & NOT_USER_GIVEN))
538+
return filter->filter_object_fn(r, filter_situation, obj,
539+
pathname, filename,
540+
filter->filter_data);
541+
/*
542+
* No filter is active or user gave object explicitly. In this case,
543+
* always show the object (except when LOFS_END_TREE, since this tree
544+
* had already been shown when LOFS_BEGIN_TREE).
545+
*/
546+
if (filter_situation == LOFS_END_TREE)
547+
return 0;
548+
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
549+
}
550+
551+
void list_objects_filter__free(struct filter *filter)
552+
{
553+
if (!filter)
554+
return;
555+
filter->free_fn(filter->filter_data);
556+
free(filter);
519557
}

list-objects-filter.h

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,30 +60,27 @@ enum list_objects_filter_situation {
6060
LOFS_BLOB
6161
};
6262

63-
typedef enum list_objects_filter_result (*filter_object_fn)(
63+
struct filter;
64+
65+
/* Constructor for the set of defined list-objects filters. */
66+
struct filter *list_objects_filter__init(
67+
struct oidset *omitted,
68+
struct list_objects_filter_options *filter_options);
69+
70+
/*
71+
* Lets `filter` decide how to handle the `obj`. If `filter` is NULL, this
72+
* function behaves as expected if no filter is configured: all objects are
73+
* included.
74+
*/
75+
enum list_objects_filter_result list_objects_filter__filter_object(
6476
struct repository *r,
6577
enum list_objects_filter_situation filter_situation,
6678
struct object *obj,
6779
const char *pathname,
6880
const char *filename,
69-
void *filter_data);
70-
71-
typedef void (*filter_free_fn)(void *filter_data);
81+
struct filter *filter);
7282

73-
/*
74-
* Constructor for the set of defined list-objects filters.
75-
* Returns a generic "void *filter_data".
76-
*
77-
* The returned "filter_fn" will be used by traverse_commit_list()
78-
* to filter the results.
79-
*
80-
* The returned "filter_free_fn" is a destructor for the
81-
* filter_data.
82-
*/
83-
void *list_objects_filter__init(
84-
struct oidset *omitted,
85-
struct list_objects_filter_options *filter_options,
86-
filter_object_fn *filter_fn,
87-
filter_free_fn *filter_free_fn);
83+
/* Destroys `filter`. Does nothing if `filter` is null. */
84+
void list_objects_filter__free(struct filter *filter);
8885

8986
#endif /* LIST_OBJECTS_FILTER_H */

list-objects.c

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ struct traversal_context {
1818
show_object_fn show_object;
1919
show_commit_fn show_commit;
2020
void *show_data;
21-
filter_object_fn filter_fn;
22-
void *filter_data;
21+
struct filter *filter;
2322
};
2423

2524
static void process_blob(struct traversal_context *ctx,
@@ -29,7 +28,7 @@ static void process_blob(struct traversal_context *ctx,
2928
{
3029
struct object *obj = &blob->object;
3130
size_t pathlen;
32-
enum list_objects_filter_result r = LOFR_MARK_SEEN | LOFR_DO_SHOW;
31+
enum list_objects_filter_result r;
3332

3433
if (!ctx->revs->blob_objects)
3534
return;
@@ -54,11 +53,10 @@ static void process_blob(struct traversal_context *ctx,
5453

5554
pathlen = path->len;
5655
strbuf_addstr(path, name);
57-
if ((obj->flags & NOT_USER_GIVEN) && ctx->filter_fn)
58-
r = ctx->filter_fn(ctx->revs->repo,
59-
LOFS_BLOB, obj,
60-
path->buf, &path->buf[pathlen],
61-
ctx->filter_data);
56+
r = list_objects_filter__filter_object(ctx->revs->repo,
57+
LOFS_BLOB, obj,
58+
path->buf, &path->buf[pathlen],
59+
ctx->filter);
6260
if (r & LOFR_MARK_SEEN)
6361
obj->flags |= SEEN;
6462
if (r & LOFR_DO_SHOW)
@@ -157,7 +155,7 @@ static void process_tree(struct traversal_context *ctx,
157155
struct object *obj = &tree->object;
158156
struct rev_info *revs = ctx->revs;
159157
int baselen = base->len;
160-
enum list_objects_filter_result r = LOFR_MARK_SEEN | LOFR_DO_SHOW;
158+
enum list_objects_filter_result r;
161159
int failed_parse;
162160

163161
if (!revs->tree_objects)
@@ -186,11 +184,10 @@ static void process_tree(struct traversal_context *ctx,
186184
}
187185

188186
strbuf_addstr(base, name);
189-
if ((obj->flags & NOT_USER_GIVEN) && ctx->filter_fn)
190-
r = ctx->filter_fn(ctx->revs->repo,
191-
LOFS_BEGIN_TREE, obj,
192-
base->buf, &base->buf[baselen],
193-
ctx->filter_data);
187+
r = list_objects_filter__filter_object(ctx->revs->repo,
188+
LOFS_BEGIN_TREE, obj,
189+
base->buf, &base->buf[baselen],
190+
ctx->filter);
194191
if (r & LOFR_MARK_SEEN)
195192
obj->flags |= SEEN;
196193
if (r & LOFR_DO_SHOW)
@@ -203,16 +200,14 @@ static void process_tree(struct traversal_context *ctx,
203200
else if (!failed_parse)
204201
process_tree_contents(ctx, tree, base);
205202

206-
if ((obj->flags & NOT_USER_GIVEN) && ctx->filter_fn) {
207-
r = ctx->filter_fn(ctx->revs->repo,
208-
LOFS_END_TREE, obj,
209-
base->buf, &base->buf[baselen],
210-
ctx->filter_data);
211-
if (r & LOFR_MARK_SEEN)
212-
obj->flags |= SEEN;
213-
if (r & LOFR_DO_SHOW)
214-
ctx->show_object(obj, base->buf, ctx->show_data);
215-
}
203+
r = list_objects_filter__filter_object(ctx->revs->repo,
204+
LOFS_END_TREE, obj,
205+
base->buf, &base->buf[baselen],
206+
ctx->filter);
207+
if (r & LOFR_MARK_SEEN)
208+
obj->flags |= SEEN;
209+
if (r & LOFR_DO_SHOW)
210+
ctx->show_object(obj, base->buf, ctx->show_data);
216211

217212
strbuf_setlen(base, baselen);
218213
free_tree_buffer(tree);
@@ -402,8 +397,7 @@ void traverse_commit_list(struct rev_info *revs,
402397
ctx.show_commit = show_commit;
403398
ctx.show_object = show_object;
404399
ctx.show_data = show_data;
405-
ctx.filter_fn = NULL;
406-
ctx.filter_data = NULL;
400+
ctx.filter = NULL;
407401
do_traverse(&ctx);
408402
}
409403

@@ -416,17 +410,12 @@ void traverse_commit_list_filtered(
416410
struct oidset *omitted)
417411
{
418412
struct traversal_context ctx;
419-
filter_free_fn filter_free_fn = NULL;
420413

421414
ctx.revs = revs;
422415
ctx.show_object = show_object;
423416
ctx.show_commit = show_commit;
424417
ctx.show_data = show_data;
425-
ctx.filter_fn = NULL;
426-
427-
ctx.filter_data = list_objects_filter__init(omitted, filter_options,
428-
&ctx.filter_fn, &filter_free_fn);
418+
ctx.filter = list_objects_filter__init(omitted, filter_options);
429419
do_traverse(&ctx);
430-
if (ctx.filter_data && filter_free_fn)
431-
filter_free_fn(ctx.filter_data);
420+
list_objects_filter__free(ctx.filter);
432421
}

0 commit comments

Comments
 (0)