Browse Source

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 <git@jeffhostetler.com>
Helped-by: Jonathan Tan <jonathantanmy@google.com>
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Matthew DeVore <matvore@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Matthew DeVore 6 years ago committed by Junio C Hamano
parent
commit
9430147ca0
  1. 110
      list-objects-filter.c
  2. 35
      list-objects-filter.h
  3. 35
      list-objects.c

110
list-objects-filter.c

@ -26,6 +26,20 @@
*/ */
#define FILTER_SHOWN_BUT_REVISIT (1<<21) #define FILTER_SHOWN_BUT_REVISIT (1<<21)


struct filter {
enum list_objects_filter_result (*filter_object_fn)(
struct repository *r,
enum list_objects_filter_situation filter_situation,
struct object *obj,
const char *pathname,
const char *filename,
void *filter_data);

void (*free_fn)(void *filter_data);

void *filter_data;
};

/* /*
* A filter for list-objects to omit ALL blobs from the traversal. * A filter for list-objects to omit ALL blobs from the traversal.
* And to OPTIONALLY collect a list of the omitted OIDs. * And to OPTIONALLY collect a list of the omitted OIDs.
@ -67,18 +81,17 @@ static enum list_objects_filter_result filter_blobs_none(
} }
} }


static void *filter_blobs_none__init( static void filter_blobs_none__init(
struct oidset *omitted, struct oidset *omitted,
struct list_objects_filter_options *filter_options, struct list_objects_filter_options *filter_options,
filter_object_fn *filter_fn, struct filter *filter)
filter_free_fn *filter_free_fn)
{ {
struct filter_blobs_none_data *d = xcalloc(1, sizeof(*d)); struct filter_blobs_none_data *d = xcalloc(1, sizeof(*d));
d->omits = omitted; d->omits = omitted;


*filter_fn = filter_blobs_none; filter->filter_data = d;
*filter_free_fn = free; filter->filter_object_fn = filter_blobs_none;
return d; filter->free_fn = free;
} }


/* /*
@ -201,11 +214,10 @@ static void filter_trees_free(void *filter_data) {
free(d); free(d);
} }


static void *filter_trees_depth__init( static void filter_trees_depth__init(
struct oidset *omitted, struct oidset *omitted,
struct list_objects_filter_options *filter_options, struct list_objects_filter_options *filter_options,
filter_object_fn *filter_fn, struct filter *filter)
filter_free_fn *filter_free_fn)
{ {
struct filter_trees_depth_data *d = xcalloc(1, sizeof(*d)); struct filter_trees_depth_data *d = xcalloc(1, sizeof(*d));
d->omits = omitted; d->omits = omitted;
@ -213,9 +225,9 @@ static void *filter_trees_depth__init(
d->exclude_depth = filter_options->tree_exclude_depth; d->exclude_depth = filter_options->tree_exclude_depth;
d->current_depth = 0; d->current_depth = 0;


*filter_fn = filter_trees_depth; filter->filter_data = d;
*filter_free_fn = filter_trees_free; filter->filter_object_fn = filter_trees_depth;
return d; filter->free_fn = filter_trees_free;
} }


/* /*
@ -281,19 +293,18 @@ include_it:
return LOFR_MARK_SEEN | LOFR_DO_SHOW; return LOFR_MARK_SEEN | LOFR_DO_SHOW;
} }


static void *filter_blobs_limit__init( static void filter_blobs_limit__init(
struct oidset *omitted, struct oidset *omitted,
struct list_objects_filter_options *filter_options, struct list_objects_filter_options *filter_options,
filter_object_fn *filter_fn, struct filter *filter)
filter_free_fn *filter_free_fn)
{ {
struct filter_blobs_limit_data *d = xcalloc(1, sizeof(*d)); struct filter_blobs_limit_data *d = xcalloc(1, sizeof(*d));
d->omits = omitted; d->omits = omitted;
d->max_bytes = filter_options->blob_limit_value; d->max_bytes = filter_options->blob_limit_value;


*filter_fn = filter_blobs_limit; filter->filter_data = d;
*filter_free_fn = free; filter->filter_object_fn = filter_blobs_limit;
return d; filter->free_fn = free;
} }


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


static void *filter_sparse_oid__init( static void filter_sparse_oid__init(
struct oidset *omitted, struct oidset *omitted,
struct list_objects_filter_options *filter_options, struct list_objects_filter_options *filter_options,
filter_object_fn *filter_fn, struct filter *filter)
filter_free_fn *filter_free_fn)
{ {
struct filter_sparse_data *d = xcalloc(1, sizeof(*d)); struct filter_sparse_data *d = xcalloc(1, sizeof(*d));
d->omits = omitted; d->omits = omitted;
@ -473,16 +483,15 @@ static void *filter_sparse_oid__init(
d->array_frame[d->nr].child_prov_omit = 0; d->array_frame[d->nr].child_prov_omit = 0;
d->nr++; d->nr++;


*filter_fn = filter_sparse; filter->filter_data = d;
*filter_free_fn = filter_sparse_free; filter->filter_object_fn = filter_sparse;
return d; filter->free_fn = filter_sparse_free;
} }


typedef void *(*filter_init_fn)( typedef void (*filter_init_fn)(
struct oidset *omitted, struct oidset *omitted,
struct list_objects_filter_options *filter_options, struct list_objects_filter_options *filter_options,
filter_object_fn *filter_fn, struct filter *filter);
filter_free_fn *filter_free_fn);


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


void *list_objects_filter__init( struct filter *list_objects_filter__init(
struct oidset *omitted, struct oidset *omitted,
struct list_objects_filter_options *filter_options, struct list_objects_filter_options *filter_options)
filter_object_fn *filter_fn,
filter_free_fn *filter_free_fn)
{ {
struct filter *filter;
filter_init_fn init_fn; filter_init_fn init_fn;


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


init_fn = s_filters[filter_options->choice]; init_fn = s_filters[filter_options->choice];
if (init_fn) if (!init_fn)
return init_fn(omitted, filter_options,
filter_fn, filter_free_fn);
*filter_fn = NULL;
*filter_free_fn = NULL;
return NULL; return NULL;

filter = xcalloc(1, sizeof(*filter));
init_fn(omitted, filter_options, filter);
return filter;
}

enum list_objects_filter_result list_objects_filter__filter_object(
struct repository *r,
enum list_objects_filter_situation filter_situation,
struct object *obj,
const char *pathname,
const char *filename,
struct filter *filter)
{
if (filter && (obj->flags & NOT_USER_GIVEN))
return filter->filter_object_fn(r, filter_situation, obj,
pathname, filename,
filter->filter_data);
/*
* No filter is active or user gave object explicitly. In this case,
* always show the object (except when LOFS_END_TREE, since this tree
* had already been shown when LOFS_BEGIN_TREE).
*/
if (filter_situation == LOFS_END_TREE)
return 0;
return LOFR_MARK_SEEN | LOFR_DO_SHOW;
}

void list_objects_filter__free(struct filter *filter)
{
if (!filter)
return;
filter->free_fn(filter->filter_data);
free(filter);
} }

35
list-objects-filter.h

@ -60,30 +60,27 @@ enum list_objects_filter_situation {
LOFS_BLOB LOFS_BLOB
}; };


typedef enum list_objects_filter_result (*filter_object_fn)( struct filter;

/* Constructor for the set of defined list-objects filters. */
struct filter *list_objects_filter__init(
struct oidset *omitted,
struct list_objects_filter_options *filter_options);

/*
* Lets `filter` decide how to handle the `obj`. If `filter` is NULL, this
* function behaves as expected if no filter is configured: all objects are
* included.
*/
enum list_objects_filter_result list_objects_filter__filter_object(
struct repository *r, struct repository *r,
enum list_objects_filter_situation filter_situation, enum list_objects_filter_situation filter_situation,
struct object *obj, struct object *obj,
const char *pathname, const char *pathname,
const char *filename, const char *filename,
void *filter_data); struct filter *filter);

typedef void (*filter_free_fn)(void *filter_data);


/* /* Destroys `filter`. Does nothing if `filter` is null. */
* Constructor for the set of defined list-objects filters. void list_objects_filter__free(struct filter *filter);
* Returns a generic "void *filter_data".
*
* The returned "filter_fn" will be used by traverse_commit_list()
* to filter the results.
*
* The returned "filter_free_fn" is a destructor for the
* filter_data.
*/
void *list_objects_filter__init(
struct oidset *omitted,
struct list_objects_filter_options *filter_options,
filter_object_fn *filter_fn,
filter_free_fn *filter_free_fn);


#endif /* LIST_OBJECTS_FILTER_H */ #endif /* LIST_OBJECTS_FILTER_H */

35
list-objects.c

@ -18,8 +18,7 @@ struct traversal_context {
show_object_fn show_object; show_object_fn show_object;
show_commit_fn show_commit; show_commit_fn show_commit;
void *show_data; void *show_data;
filter_object_fn filter_fn; struct filter *filter;
void *filter_data;
}; };


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


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


pathlen = path->len; pathlen = path->len;
strbuf_addstr(path, name); strbuf_addstr(path, name);
if ((obj->flags & NOT_USER_GIVEN) && ctx->filter_fn) r = list_objects_filter__filter_object(ctx->revs->repo,
r = ctx->filter_fn(ctx->revs->repo,
LOFS_BLOB, obj, LOFS_BLOB, obj,
path->buf, &path->buf[pathlen], path->buf, &path->buf[pathlen],
ctx->filter_data); ctx->filter);
if (r & LOFR_MARK_SEEN) if (r & LOFR_MARK_SEEN)
obj->flags |= SEEN; obj->flags |= SEEN;
if (r & LOFR_DO_SHOW) if (r & LOFR_DO_SHOW)
@ -157,7 +155,7 @@ static void process_tree(struct traversal_context *ctx,
struct object *obj = &tree->object; struct object *obj = &tree->object;
struct rev_info *revs = ctx->revs; struct rev_info *revs = ctx->revs;
int baselen = base->len; int baselen = base->len;
enum list_objects_filter_result r = LOFR_MARK_SEEN | LOFR_DO_SHOW; enum list_objects_filter_result r;
int failed_parse; int failed_parse;


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


strbuf_addstr(base, name); strbuf_addstr(base, name);
if ((obj->flags & NOT_USER_GIVEN) && ctx->filter_fn) r = list_objects_filter__filter_object(ctx->revs->repo,
r = ctx->filter_fn(ctx->revs->repo,
LOFS_BEGIN_TREE, obj, LOFS_BEGIN_TREE, obj,
base->buf, &base->buf[baselen], base->buf, &base->buf[baselen],
ctx->filter_data); ctx->filter);
if (r & LOFR_MARK_SEEN) if (r & LOFR_MARK_SEEN)
obj->flags |= SEEN; obj->flags |= SEEN;
if (r & LOFR_DO_SHOW) if (r & LOFR_DO_SHOW)
@ -203,16 +200,14 @@ static void process_tree(struct traversal_context *ctx,
else if (!failed_parse) else if (!failed_parse)
process_tree_contents(ctx, tree, base); process_tree_contents(ctx, tree, base);


if ((obj->flags & NOT_USER_GIVEN) && ctx->filter_fn) { r = list_objects_filter__filter_object(ctx->revs->repo,
r = ctx->filter_fn(ctx->revs->repo,
LOFS_END_TREE, obj, LOFS_END_TREE, obj,
base->buf, &base->buf[baselen], base->buf, &base->buf[baselen],
ctx->filter_data); ctx->filter);
if (r & LOFR_MARK_SEEN) if (r & LOFR_MARK_SEEN)
obj->flags |= SEEN; obj->flags |= SEEN;
if (r & LOFR_DO_SHOW) if (r & LOFR_DO_SHOW)
ctx->show_object(obj, base->buf, ctx->show_data); ctx->show_object(obj, base->buf, ctx->show_data);
}


strbuf_setlen(base, baselen); strbuf_setlen(base, baselen);
free_tree_buffer(tree); free_tree_buffer(tree);
@ -402,8 +397,7 @@ void traverse_commit_list(struct rev_info *revs,
ctx.show_commit = show_commit; ctx.show_commit = show_commit;
ctx.show_object = show_object; ctx.show_object = show_object;
ctx.show_data = show_data; ctx.show_data = show_data;
ctx.filter_fn = NULL; ctx.filter = NULL;
ctx.filter_data = NULL;
do_traverse(&ctx); do_traverse(&ctx);
} }


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


ctx.revs = revs; ctx.revs = revs;
ctx.show_object = show_object; ctx.show_object = show_object;
ctx.show_commit = show_commit; ctx.show_commit = show_commit;
ctx.show_data = show_data; ctx.show_data = show_data;
ctx.filter_fn = NULL; ctx.filter = list_objects_filter__init(omitted, filter_options);

ctx.filter_data = list_objects_filter__init(omitted, filter_options,
&ctx.filter_fn, &filter_free_fn);
do_traverse(&ctx); do_traverse(&ctx);
if (ctx.filter_data && filter_free_fn) list_objects_filter__free(ctx.filter);
filter_free_fn(ctx.filter_data);
} }

Loading…
Cancel
Save