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>
This commit is contained in:
parent
8dca754b1e
commit
9430147ca0
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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. */
|
||||||
|
void list_objects_filter__free(struct filter *filter);
|
||||||
/*
|
|
||||||
* Constructor for the set of defined list-objects filters.
|
|
||||||
* 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 */
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user