On Fri, Jul 31, 2020 at 05:36:04PM -0400, Jeff King wrote: > My suggested patch does introduce more side effects. I think that's OK > because there really is only a single caller here. But if you wanted it > cleaner, then I think having allows_filter_choice() fill out an error > strbuf would eliminate my concern without drastically altering the flow > of your code. That could be something like the patch below. banned_filter() could switch to returning a simple boolean, but I didn't do that here. I did (as with my other patch) reorder the logic in allows_filter_choice(), as I think it's much easier to follow by resolving "allowed" to the fallback earlier. That lets you handle "not allowed at all" first and early-return (or die) before dealing with type-specific checks. diff --git a/upload-pack.c b/upload-pack.c index 131445b212..86786f0e13 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -993,59 +993,60 @@ static int process_deepen_not(const char *line, struct string_list *deepen_not, } static int allows_filter_choice(struct upload_pack_data *data, - struct list_objects_filter_options *opts) + struct list_objects_filter_options *opts, + struct strbuf *err) { const char *key = list_object_filter_config_name(opts->choice); struct string_list_item *item = string_list_lookup(&data->allowed_filters, key); - int allowed = -1; + int allowed; if (item) allowed = (intptr_t) item->util; + else + allowed = data->allow_filter_fallback; - if (allowed != 0 && - opts->choice == LOFC_TREE_DEPTH && - opts->tree_exclude_depth > data->tree_filter_max_depth) + if (!allowed) { + strbuf_addf(err, "filter '%s' not supported", key); return 0; + } + + if (opts->choice == LOFC_TREE_DEPTH && + opts->tree_exclude_depth > data->tree_filter_max_depth) { + strbuf_addf(err, "tree filter maximum depth is %lu, but got %lu", + data->tree_filter_max_depth, opts->tree_exclude_depth); + return 0; + } - if (allowed > -1) - return allowed; - return data->allow_filter_fallback; + return 1; } static struct list_objects_filter_options *banned_filter( struct upload_pack_data *data, - struct list_objects_filter_options *opts) + struct list_objects_filter_options *opts, + struct strbuf *err) { size_t i; - if (!allows_filter_choice(data, opts)) + if (!allows_filter_choice(data, opts, err)) return opts; if (opts->choice == LOFC_COMBINE) for (i = 0; i < opts->sub_nr; i++) { struct list_objects_filter_options *sub = &opts->sub[i]; - if (banned_filter(data, sub)) + if (banned_filter(data, sub, err)) return sub; } return NULL; } static void die_if_using_banned_filter(struct upload_pack_data *data) { - struct list_objects_filter_options *banned = banned_filter(data, - &data->filter_options); struct strbuf buf = STRBUF_INIT; + struct list_objects_filter_options *banned = + banned_filter(data, &data->filter_options, &buf); if (!banned) return; - strbuf_addf(&buf, "git upload-pack: filter '%s' not supported", - list_object_filter_config_name(banned->choice)); - if (banned->choice == LOFC_TREE_DEPTH && - data->tree_filter_max_depth != ULONG_MAX) - strbuf_addf(&buf, _(" (maximum depth: %lu, but got: %lu)"), - data->tree_filter_max_depth, - banned->tree_exclude_depth); - packet_writer_error(&data->writer, "%s\n", buf.buf); die("%s", buf.buf); }