diff options
author | Vincent Ambo <tazjin@google.com> | 2020-05-25T23·06+0100 |
---|---|---|
committer | Vincent Ambo <tazjin@google.com> | 2020-05-25T23·06+0100 |
commit | 93ba78d6f4632ef1c5228965e3edc8c0faf88c1e (patch) | |
tree | 85730c182a9f5f492ade8e8ccdb1c2356f9900bd /third_party/git/list-objects-filter.c | |
parent | 6f8fbf4aa4b1654ab27d4829e114538761817de0 (diff) |
revert(3p/git): Revert merge of git upstream at v2.26.2 r/852
This causes cgit to serve error pages, which is undesirable. This reverts commit 5229c9b232de5bfa959ad6ebbb4c8192ac513352, reversing changes made to f2b211131f2347342dde63975b09cf603149f1a3.
Diffstat (limited to 'third_party/git/list-objects-filter.c')
-rw-r--r-- | third_party/git/list-objects-filter.c | 382 |
1 files changed, 95 insertions, 287 deletions
diff --git a/third_party/git/list-objects-filter.c b/third_party/git/list-objects-filter.c index 1e8d4e763da0..36e1f774bcfc 100644 --- a/third_party/git/list-objects-filter.c +++ b/third_party/git/list-objects-filter.c @@ -26,46 +26,11 @@ */ #define FILTER_SHOWN_BUT_REVISIT (1<<21) -struct subfilter { - struct filter *filter; - struct oidset seen; - struct oidset omits; - struct object_id skip_tree; - unsigned is_skipping_tree : 1; -}; - -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, - struct oidset *omits, - void *filter_data); - - /* - * Optional. If this function is supplied and the filter needs - * to collect omits, then this function is called once before - * free_fn is called. - * - * This is required because the following two conditions hold: - * - * a. A tree filter can add and remove objects as an object - * graph is traversed. - * b. A combine filter's omit set is the union of all its - * subfilters, which may include tree: filters. - * - * As such, the omits sets must be separate sets, and can only - * be unioned after the traversal is completed. - */ - void (*finalize_omits_fn)(struct oidset *omits, void *filter_data); - - void (*free_fn)(void *filter_data); - - void *filter_data; - - /* If non-NULL, the filter collects a list of the omitted OIDs here. */ +/* + * A filter for list-objects to omit ALL blobs from the traversal. + * And to OPTIONALLY collect a list of the omitted OIDs. + */ +struct filter_blobs_none_data { struct oidset *omits; }; @@ -75,9 +40,10 @@ static enum list_objects_filter_result filter_blobs_none( struct object *obj, const char *pathname, const char *filename, - struct oidset *omits, void *filter_data_) { + struct filter_blobs_none_data *filter_data = filter_data_; + switch (filter_situation) { default: BUG("unknown filter_situation: %d", filter_situation); @@ -95,18 +61,24 @@ static enum list_objects_filter_result filter_blobs_none( assert(obj->type == OBJ_BLOB); assert((obj->flags & SEEN) == 0); - if (omits) - oidset_insert(omits, &obj->oid); + if (filter_data->omits) + oidset_insert(filter_data->omits, &obj->oid); return LOFR_MARK_SEEN; /* but not LOFR_DO_SHOW (hard omit) */ } } -static void filter_blobs_none__init( +static void *filter_blobs_none__init( + struct oidset *omitted, struct list_objects_filter_options *filter_options, - struct filter *filter) + filter_object_fn *filter_fn, + filter_free_fn *filter_free_fn) { - filter->filter_object_fn = filter_blobs_none; - filter->free_fn = free; + struct filter_blobs_none_data *d = xcalloc(1, sizeof(*d)); + d->omits = omitted; + + *filter_fn = filter_blobs_none; + *filter_free_fn = free; + return d; } /* @@ -114,6 +86,8 @@ static void filter_blobs_none__init( * Can OPTIONALLY collect a list of the omitted OIDs. */ struct filter_trees_depth_data { + struct oidset *omits; + /* * Maps trees to the minimum depth at which they were seen. It is not * necessary to re-traverse a tree at deeper or equal depths than it has @@ -136,16 +110,16 @@ struct seen_map_entry { /* Returns 1 if the oid was in the omits set before it was invoked. */ static int filter_trees_update_omits( struct object *obj, - struct oidset *omits, + struct filter_trees_depth_data *filter_data, int include_it) { - if (!omits) + if (!filter_data->omits) return 0; if (include_it) - return oidset_remove(omits, &obj->oid); + return oidset_remove(filter_data->omits, &obj->oid); else - return oidset_insert(omits, &obj->oid); + return oidset_insert(filter_data->omits, &obj->oid); } static enum list_objects_filter_result filter_trees_depth( @@ -154,7 +128,6 @@ static enum list_objects_filter_result filter_trees_depth( struct object *obj, const char *pathname, const char *filename, - struct oidset *omits, void *filter_data_) { struct filter_trees_depth_data *filter_data = filter_data_; @@ -179,7 +152,7 @@ static enum list_objects_filter_result filter_trees_depth( return LOFR_ZERO; case LOFS_BLOB: - filter_trees_update_omits(obj, omits, include_it); + filter_trees_update_omits(obj, filter_data, include_it); return include_it ? LOFR_MARK_SEEN | LOFR_DO_SHOW : LOFR_ZERO; case LOFS_BEGIN_TREE: @@ -200,12 +173,12 @@ static enum list_objects_filter_result filter_trees_depth( filter_res = LOFR_SKIP_TREE; } else { int been_omitted = filter_trees_update_omits( - obj, omits, include_it); + obj, filter_data, include_it); seen_info->depth = filter_data->current_depth; if (include_it) filter_res = LOFR_DO_SHOW; - else if (omits && !been_omitted) + else if (filter_data->omits && !been_omitted) /* * Must update omit information of children * recursively; they have not been omitted yet. @@ -228,18 +201,21 @@ static void filter_trees_free(void *filter_data) { free(d); } -static void filter_trees_depth__init( +static void *filter_trees_depth__init( + struct oidset *omitted, struct list_objects_filter_options *filter_options, - struct filter *filter) + filter_object_fn *filter_fn, + filter_free_fn *filter_free_fn) { struct filter_trees_depth_data *d = xcalloc(1, sizeof(*d)); + d->omits = omitted; oidmap_init(&d->seen_at_depth, 0); d->exclude_depth = filter_options->tree_exclude_depth; d->current_depth = 0; - filter->filter_data = d; - filter->filter_object_fn = filter_trees_depth; - filter->free_fn = filter_trees_free; + *filter_fn = filter_trees_depth; + *filter_free_fn = filter_trees_free; + return d; } /* @@ -247,6 +223,7 @@ static void filter_trees_depth__init( * And to OPTIONALLY collect a list of the omitted OIDs. */ struct filter_blobs_limit_data { + struct oidset *omits; unsigned long max_bytes; }; @@ -256,7 +233,6 @@ static enum list_objects_filter_result filter_blobs_limit( struct object *obj, const char *pathname, const char *filename, - struct oidset *omits, void *filter_data_) { struct filter_blobs_limit_data *filter_data = filter_data_; @@ -294,27 +270,30 @@ static enum list_objects_filter_result filter_blobs_limit( if (object_length < filter_data->max_bytes) goto include_it; - if (omits) - oidset_insert(omits, &obj->oid); + if (filter_data->omits) + oidset_insert(filter_data->omits, &obj->oid); return LOFR_MARK_SEEN; /* but not LOFR_DO_SHOW (hard omit) */ } include_it: - if (omits) - oidset_remove(omits, &obj->oid); + if (filter_data->omits) + oidset_remove(filter_data->omits, &obj->oid); return LOFR_MARK_SEEN | LOFR_DO_SHOW; } -static void filter_blobs_limit__init( +static void *filter_blobs_limit__init( + struct oidset *omitted, struct list_objects_filter_options *filter_options, - struct filter *filter) + filter_object_fn *filter_fn, + filter_free_fn *filter_free_fn) { struct filter_blobs_limit_data *d = xcalloc(1, sizeof(*d)); + d->omits = omitted; d->max_bytes = filter_options->blob_limit_value; - filter->filter_data = d; - filter->filter_object_fn = filter_blobs_limit; - filter->free_fn = free; + *filter_fn = filter_blobs_limit; + *filter_free_fn = free; + return d; } /* @@ -328,12 +307,12 @@ static void filter_blobs_limit__init( */ struct frame { /* - * default_match is the usual default include/exclude value that + * defval is the usual default include/exclude value that * should be inherited as we recurse into directories based * upon pattern matching of the directory itself or of a * containing directory. */ - enum pattern_match_result default_match; + int defval; /* * 1 if the directory (recursively) contains any provisionally @@ -347,7 +326,8 @@ struct frame { }; struct filter_sparse_data { - struct pattern_list pl; + struct oidset *omits; + struct exclude_list el; size_t nr, alloc; struct frame *array_frame; @@ -359,13 +339,11 @@ static enum list_objects_filter_result filter_sparse( struct object *obj, const char *pathname, const char *filename, - struct oidset *omits, void *filter_data_) { struct filter_sparse_data *filter_data = filter_data_; - int dtype; + int val, dtype; struct frame *frame; - enum pattern_match_result match; switch (filter_situation) { default: @@ -374,15 +352,15 @@ static enum list_objects_filter_result filter_sparse( case LOFS_BEGIN_TREE: assert(obj->type == OBJ_TREE); dtype = DT_DIR; - match = path_matches_pattern_list(pathname, strlen(pathname), - filename, &dtype, &filter_data->pl, - r->index); - if (match == UNDECIDED) - match = filter_data->array_frame[filter_data->nr - 1].default_match; + val = is_excluded_from_list(pathname, strlen(pathname), + filename, &dtype, &filter_data->el, + r->index); + if (val < 0) + val = filter_data->array_frame[filter_data->nr - 1].defval; ALLOC_GROW(filter_data->array_frame, filter_data->nr + 1, filter_data->alloc); - filter_data->array_frame[filter_data->nr].default_match = match; + filter_data->array_frame[filter_data->nr].defval = val; filter_data->array_frame[filter_data->nr].child_prov_omit = 0; filter_data->nr++; @@ -436,14 +414,14 @@ static enum list_objects_filter_result filter_sparse( frame = &filter_data->array_frame[filter_data->nr - 1]; dtype = DT_REG; - match = path_matches_pattern_list(pathname, strlen(pathname), - filename, &dtype, &filter_data->pl, + val = is_excluded_from_list(pathname, strlen(pathname), + filename, &dtype, &filter_data->el, r->index); - if (match == UNDECIDED) - match = frame->default_match; - if (match == MATCHED) { - if (omits) - oidset_remove(omits, &obj->oid); + if (val < 0) + val = frame->defval; + if (val > 0) { + if (filter_data->omits) + oidset_remove(filter_data->omits, &obj->oid); return LOFR_MARK_SEEN | LOFR_DO_SHOW; } @@ -457,8 +435,8 @@ static enum list_objects_filter_result filter_sparse( * Leave the LOFR_ bits unset so that if the blob appears * again in the traversal, we will be asked again. */ - if (omits) - oidset_insert(omits, &obj->oid); + if (filter_data->omits) + oidset_insert(filter_data->omits, &obj->oid); /* * Remember that at least 1 blob in this tree was @@ -478,169 +456,33 @@ static void filter_sparse_free(void *filter_data) free(d); } -static void filter_sparse_oid__init( +static void *filter_sparse_oid__init( + struct oidset *omitted, struct list_objects_filter_options *filter_options, - struct filter *filter) + filter_object_fn *filter_fn, + filter_free_fn *filter_free_fn) { struct filter_sparse_data *d = xcalloc(1, sizeof(*d)); - struct object_context oc; - struct object_id sparse_oid; - - if (get_oid_with_context(the_repository, - filter_options->sparse_oid_name, - GET_OID_BLOB, &sparse_oid, &oc)) - die(_("unable to access sparse blob in '%s'"), - filter_options->sparse_oid_name); - if (add_patterns_from_blob_to_list(&sparse_oid, "", 0, &d->pl) < 0) - die(_("unable to parse sparse filter data in %s"), - oid_to_hex(&sparse_oid)); + d->omits = omitted; + if (add_excludes_from_blob_to_list(filter_options->sparse_oid_value, + NULL, 0, &d->el) < 0) + die("could not load filter specification"); ALLOC_GROW(d->array_frame, d->nr + 1, d->alloc); - d->array_frame[d->nr].default_match = 0; /* default to include */ + d->array_frame[d->nr].defval = 0; /* default to include */ d->array_frame[d->nr].child_prov_omit = 0; d->nr++; - filter->filter_data = d; - filter->filter_object_fn = filter_sparse; - filter->free_fn = filter_sparse_free; -} - -/* A filter which only shows objects shown by all sub-filters. */ -struct combine_filter_data { - struct subfilter *sub; - size_t nr; -}; - -static enum list_objects_filter_result process_subfilter( - struct repository *r, - enum list_objects_filter_situation filter_situation, - struct object *obj, - const char *pathname, - const char *filename, - struct subfilter *sub) -{ - enum list_objects_filter_result result; - - /* - * Check and update is_skipping_tree before oidset_contains so - * that is_skipping_tree gets unset even when the object is - * marked as seen. As of this writing, no filter uses - * LOFR_MARK_SEEN on trees that also uses LOFR_SKIP_TREE, so the - * ordering is only theoretically important. Be cautious if you - * change the order of the below checks and more filters have - * been added! - */ - if (sub->is_skipping_tree) { - if (filter_situation == LOFS_END_TREE && - oideq(&obj->oid, &sub->skip_tree)) - sub->is_skipping_tree = 0; - else - return LOFR_ZERO; - } - if (oidset_contains(&sub->seen, &obj->oid)) - return LOFR_ZERO; - - result = list_objects_filter__filter_object( - r, filter_situation, obj, pathname, filename, sub->filter); - - if (result & LOFR_MARK_SEEN) - oidset_insert(&sub->seen, &obj->oid); - - if (result & LOFR_SKIP_TREE) { - sub->is_skipping_tree = 1; - sub->skip_tree = obj->oid; - } - - return result; + *filter_fn = filter_sparse; + *filter_free_fn = filter_sparse_free; + return d; } -static enum list_objects_filter_result filter_combine( - struct repository *r, - enum list_objects_filter_situation filter_situation, - struct object *obj, - const char *pathname, - const char *filename, - struct oidset *omits, - void *filter_data) -{ - struct combine_filter_data *d = filter_data; - enum list_objects_filter_result combined_result = - LOFR_DO_SHOW | LOFR_MARK_SEEN | LOFR_SKIP_TREE; - size_t sub; - - for (sub = 0; sub < d->nr; sub++) { - enum list_objects_filter_result sub_result = process_subfilter( - r, filter_situation, obj, pathname, filename, - &d->sub[sub]); - if (!(sub_result & LOFR_DO_SHOW)) - combined_result &= ~LOFR_DO_SHOW; - if (!(sub_result & LOFR_MARK_SEEN)) - combined_result &= ~LOFR_MARK_SEEN; - if (!d->sub[sub].is_skipping_tree) - combined_result &= ~LOFR_SKIP_TREE; - } - - return combined_result; -} - -static void filter_combine__free(void *filter_data) -{ - struct combine_filter_data *d = filter_data; - size_t sub; - for (sub = 0; sub < d->nr; sub++) { - list_objects_filter__free(d->sub[sub].filter); - oidset_clear(&d->sub[sub].seen); - if (d->sub[sub].omits.set.size) - BUG("expected oidset to be cleared already"); - } - free(d->sub); -} - -static void add_all(struct oidset *dest, struct oidset *src) { - struct oidset_iter iter; - struct object_id *src_oid; - - oidset_iter_init(src, &iter); - while ((src_oid = oidset_iter_next(&iter)) != NULL) - oidset_insert(dest, src_oid); -} - -static void filter_combine__finalize_omits( - struct oidset *omits, - void *filter_data) -{ - struct combine_filter_data *d = filter_data; - size_t sub; - - for (sub = 0; sub < d->nr; sub++) { - add_all(omits, &d->sub[sub].omits); - oidset_clear(&d->sub[sub].omits); - } -} - -static void filter_combine__init( - struct list_objects_filter_options *filter_options, - struct filter* filter) -{ - struct combine_filter_data *d = xcalloc(1, sizeof(*d)); - size_t sub; - - d->nr = filter_options->sub_nr; - d->sub = xcalloc(d->nr, sizeof(*d->sub)); - for (sub = 0; sub < d->nr; sub++) - d->sub[sub].filter = list_objects_filter__init( - filter->omits ? &d->sub[sub].omits : NULL, - &filter_options->sub[sub]); - - filter->filter_data = d; - filter->filter_object_fn = filter_combine; - filter->free_fn = filter_combine__free; - filter->finalize_omits_fn = filter_combine__finalize_omits; -} - -typedef void (*filter_init_fn)( +typedef void *(*filter_init_fn)( + struct oidset *omitted, struct list_objects_filter_options *filter_options, - struct filter *filter); + filter_object_fn *filter_fn, + filter_free_fn *filter_free_fn); /* * Must match "enum list_objects_filter_choice". @@ -651,14 +493,14 @@ static filter_init_fn s_filters[] = { filter_blobs_limit__init, filter_trees_depth__init, filter_sparse_oid__init, - filter_combine__init, }; -struct filter *list_objects_filter__init( +void *list_objects_filter__init( 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; assert((sizeof(s_filters) / sizeof(s_filters[0])) == LOFC__COUNT); @@ -668,44 +510,10 @@ struct filter *list_objects_filter__init( filter_options->choice); init_fn = s_filters[filter_options->choice]; - if (!init_fn) - return NULL; - - filter = xcalloc(1, sizeof(*filter)); - filter->omits = omitted; - init_fn(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->omits, - 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; - if (filter->finalize_omits_fn && filter->omits) - filter->finalize_omits_fn(filter->omits, filter->filter_data); - filter->free_fn(filter->filter_data); - free(filter); + if (init_fn) + return init_fn(omitted, filter_options, + filter_fn, filter_free_fn); + *filter_fn = NULL; + *filter_free_fn = NULL; + return NULL; } |