git/list-objects-filter-options.h
Jeff King c54980ab83 list-objects-filter: convert filter_spec to a strbuf
Originally, the filter_spec field was just a string pointer. In
cf9ceb5a12 (list-objects-filter-options: make filter_spec a string_list,
2019-06-27) it became a string_list, but that commit notes:

    A strbuf would seem to be a more natural choice for this object, but
    it unfortunately requires initialization besides just zero'ing out
    the memory.  This results in all container structs, and all
    containers of those structs, etc., to also require initialization.
    Initializing them all would be more cumbersome that simply using a
    string_list, which behaves properly when its contents are zero'd.

Now that we've changed the struct to require non-zero initialization
anyway (ironically, because string_list also needed non-zero
initialization to avoid leaks), we can now convert to that more natural
type.

This makes the list_objects_filter_spec() function much less awkward, as
it had to collapse the string_list to a single-entry list on the fly.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-09-12 08:38:59 -07:00

177 lines
5.7 KiB
C

#ifndef LIST_OBJECTS_FILTER_OPTIONS_H
#define LIST_OBJECTS_FILTER_OPTIONS_H
#include "cache.h"
#include "parse-options.h"
#include "string-list.h"
/*
* The list of defined filters for list-objects.
*/
enum list_objects_filter_choice {
LOFC_DISABLED = 0,
LOFC_BLOB_NONE,
LOFC_BLOB_LIMIT,
LOFC_TREE_DEPTH,
LOFC_SPARSE_OID,
LOFC_OBJECT_TYPE,
LOFC_COMBINE,
LOFC__COUNT /* must be last */
};
/*
* Returns a configuration key suitable for describing the given object filter,
* e.g.: "blob:none", "combine", etc.
*/
const char *list_object_filter_config_name(enum list_objects_filter_choice c);
struct list_objects_filter_options {
/*
* 'filter_spec' is the raw argument value given on the command line
* or protocol request. (The part after the "--keyword=".) For
* commands that launch filtering sub-processes, or for communication
* over the network, don't use this value; use the result of
* expand_list_objects_filter_spec() instead.
* To get the raw filter spec given by the user, use the result of
* list_objects_filter_spec().
*/
struct strbuf filter_spec;
/*
* 'choice' is determined by parsing the filter-spec. This indicates
* the filtering algorithm to use.
*/
enum list_objects_filter_choice choice;
/*
* Choice is LOFC_DISABLED because "--no-filter" was requested.
*/
unsigned int no_filter : 1;
/*
* BEGIN choice-specific parsed values from within the filter-spec. Only
* some values will be defined for any given choice.
*/
char *sparse_oid_name;
unsigned long blob_limit_value;
unsigned long tree_exclude_depth;
enum object_type object_type;
/* LOFC_COMBINE values */
/* This array contains all the subfilters which this filter combines. */
size_t sub_nr, sub_alloc;
struct list_objects_filter_options *sub;
/*
* END choice-specific parsed values.
*/
};
#define LIST_OBJECTS_FILTER_INIT { .filter_spec = STRBUF_INIT }
void list_objects_filter_init(struct list_objects_filter_options *filter_options);
/*
* Parse value of the argument to the "filter" keyword.
* On the command line this looks like:
* --filter=<arg>
* and in the pack protocol as:
* "filter" SP <arg>
*
* The filter keyword will be used by many commands.
* See Documentation/rev-list-options.txt for allowed values for <arg>.
*
* Capture the given arg as the "filter_spec". This can be forwarded to
* subordinate commands when necessary (although it's better to pass it through
* expand_list_objects_filter_spec() first). We also "intern" the arg for the
* convenience of the current command.
*/
int gently_parse_list_objects_filter(
struct list_objects_filter_options *filter_options,
const char *arg,
struct strbuf *errbuf);
void list_objects_filter_die_if_populated(
struct list_objects_filter_options *filter_options);
/*
* Parses the filter spec string given by arg and either (1) simply places the
* result in filter_options if it is not yet populated or (2) combines it with
* the filter already in filter_options if it is already populated. In the case
* of (2), the filter specs are combined as if specified with 'combine:'.
*
* Dies and prints a user-facing message if an error occurs.
*/
void parse_list_objects_filter(
struct list_objects_filter_options *filter_options,
const char *arg);
/**
* The opt->value to opt_parse_list_objects_filter() is either a
* "struct list_objects_filter_option *" when using
* OPT_PARSE_LIST_OBJECTS_FILTER().
*
* Or, if using no "struct option" field is used by the callback,
* except the "defval" which is expected to be an "opt_lof_init"
* function, which is called with the "opt->value" and must return a
* pointer to the ""struct list_objects_filter_option *" to be used.
*
* The OPT_PARSE_LIST_OBJECTS_FILTER_INIT() can be used e.g. the
* "struct list_objects_filter_option" is embedded in a "struct
* rev_info", which the "defval" could be tasked with lazily
* initializing. See cmd_pack_objects() for an example.
*/
int opt_parse_list_objects_filter(const struct option *opt,
const char *arg, int unset);
typedef struct list_objects_filter_options *(*opt_lof_init)(void *);
#define OPT_PARSE_LIST_OBJECTS_FILTER_INIT(fo, init) \
{ OPTION_CALLBACK, 0, "filter", (fo), N_("args"), \
N_("object filtering"), 0, opt_parse_list_objects_filter, \
(intptr_t)(init) }
#define OPT_PARSE_LIST_OBJECTS_FILTER(fo) \
OPT_PARSE_LIST_OBJECTS_FILTER_INIT((fo), NULL)
/*
* Translates abbreviated numbers in the filter's filter_spec into their
* fully-expanded forms (e.g., "limit:blob=1k" becomes "limit:blob=1024").
* Returns a string owned by the list_objects_filter_options object.
*
* This form should be used instead of the raw list_objects_filter_spec()
* value when communicating with a remote process or subprocess.
*/
const char *expand_list_objects_filter_spec(
struct list_objects_filter_options *filter);
/*
* Returns the filter spec string more or less in the form as the user
* entered it. This form of the filter_spec can be used in user-facing
* messages. Returns a string owned by the list_objects_filter_options
* object.
*/
const char *list_objects_filter_spec(
struct list_objects_filter_options *filter);
void list_objects_filter_release(
struct list_objects_filter_options *filter_options);
static inline void list_objects_filter_set_no_filter(
struct list_objects_filter_options *filter_options)
{
list_objects_filter_release(filter_options);
filter_options->no_filter = 1;
}
void partial_clone_register(
const char *remote,
struct list_objects_filter_options *filter_options);
void partial_clone_get_default_filter_spec(
struct list_objects_filter_options *filter_options,
const char *remote);
void list_objects_filter_copy(
struct list_objects_filter_options *dest,
const struct list_objects_filter_options *src);
#endif /* LIST_OBJECTS_FILTER_OPTIONS_H */