2017-11-21 20:58:50 +00:00
|
|
|
#ifndef LIST_OBJECTS_FILTER_OPTIONS_H
|
|
|
|
#define LIST_OBJECTS_FILTER_OPTIONS_H
|
|
|
|
|
|
|
|
#include "parse-options.h"
|
2019-06-27 22:54:10 +00:00
|
|
|
#include "string-list.h"
|
2017-11-21 20:58:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The list of defined filters for list-objects.
|
|
|
|
*/
|
|
|
|
enum list_objects_filter_choice {
|
|
|
|
LOFC_DISABLED = 0,
|
|
|
|
LOFC_BLOB_NONE,
|
|
|
|
LOFC_BLOB_LIMIT,
|
2019-01-09 02:59:13 +00:00
|
|
|
LOFC_TREE_DEPTH,
|
2017-11-21 20:58:50 +00:00
|
|
|
LOFC_SPARSE_OID,
|
2019-06-27 22:54:08 +00:00
|
|
|
LOFC_COMBINE,
|
2017-11-21 20:58:50 +00:00
|
|
|
LOFC__COUNT /* must be last */
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
2019-01-08 00:17:09 +00:00
|
|
|
* 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.
|
2019-06-27 22:54:10 +00:00
|
|
|
* To get the raw filter spec given by the user, use the result of
|
|
|
|
* list_objects_filter_spec().
|
2017-11-21 20:58:50 +00:00
|
|
|
*/
|
2019-06-27 22:54:10 +00:00
|
|
|
struct string_list filter_spec;
|
2017-11-21 20:58:50 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 'choice' is determined by parsing the filter-spec. This indicates
|
|
|
|
* the filtering algorithm to use.
|
|
|
|
*/
|
|
|
|
enum list_objects_filter_choice choice;
|
|
|
|
|
2017-12-08 15:58:50 +00:00
|
|
|
/*
|
|
|
|
* Choice is LOFC_DISABLED because "--no-filter" was requested.
|
|
|
|
*/
|
|
|
|
unsigned int no_filter : 1;
|
|
|
|
|
2017-11-21 20:58:50 +00:00
|
|
|
/*
|
2019-06-27 22:54:08 +00:00
|
|
|
* BEGIN choice-specific parsed values from within the filter-spec. Only
|
|
|
|
* some values will be defined for any given choice.
|
2017-11-21 20:58:50 +00:00
|
|
|
*/
|
2019-06-27 22:54:08 +00:00
|
|
|
|
list-objects-filter: delay parsing of sparse oid
The list-objects-filter code has two steps to its initialization:
1. parse_list_objects_filter() makes sure the spec is a filter we know
about and is syntactically correct. This step is done by "rev-list"
or "upload-pack" that is going to apply a filter, but also by "git
clone" or "git fetch" before they send the spec across the wire.
2. list_objects_filter__init() runs the type-specific initialization
(using function pointers established in step 1). This happens at
the start of traverse_commit_list_filtered(), when we're about to
actually use the filter.
It's a good idea to parse as much as we can in step 1, in order to catch
problems early (e.g., a blob size limit that isn't a number). But one
thing we _shouldn't_ do is resolve any oids at that step (e.g., for
sparse-file contents specified by oid). In the case of a fetch, the oid
has to be resolved on the remote side.
The current code does resolve the oid during the parse phase, but
ignores any error (which we must do, because we might just be sending
the spec across the wire). This leads to two bugs:
- if we're not in a repository (e.g., because it's git-clone parsing
the spec), then we trigger a BUG() trying to resolve the name
- if we did hit the error case, we still have to notice that later and
bail. The code path in rev-list handles this, but the one in
upload-pack does not, leading to a segfault.
We can fix both by moving the oid resolution into the sparse-oid init
function. At that point we know we have a repository (because we're
about to traverse), and handling the error there fixes the segfault.
As a bonus, we can drop the NULL sparse_oid_value check in rev-list,
since this is now handled in the sparse-oid-filter init function.
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-09-15 16:12:44 +00:00
|
|
|
char *sparse_oid_name;
|
2017-11-21 20:58:50 +00:00
|
|
|
unsigned long blob_limit_value;
|
2019-01-09 02:59:13 +00:00
|
|
|
unsigned long tree_exclude_depth;
|
2019-06-27 22:54:08 +00:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2017-11-21 20:58:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Normalized command line arguments */
|
|
|
|
#define CL_ARG__FILTER "filter"
|
|
|
|
|
2019-06-27 22:54:12 +00:00
|
|
|
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.
|
|
|
|
*/
|
2019-06-27 22:54:14 +00:00
|
|
|
void parse_list_objects_filter(
|
2017-11-21 20:58:50 +00:00
|
|
|
struct list_objects_filter_options *filter_options,
|
|
|
|
const char *arg);
|
|
|
|
|
|
|
|
int opt_parse_list_objects_filter(const struct option *opt,
|
|
|
|
const char *arg, int unset);
|
|
|
|
|
|
|
|
#define OPT_PARSE_LIST_OBJECTS_FILTER(fo) \
|
Use OPT_CALLBACK and OPT_CALLBACK_F
In the codebase, there are many options which use OPTION_CALLBACK in a
plain ol' struct definition. However, we have the OPT_CALLBACK and
OPT_CALLBACK_F macros which are meant to abstract these plain struct
definitions away. These macros are useful as they semantically signal to
developers that these are just normal callback option with nothing fancy
happening.
Replace plain struct definitions of OPTION_CALLBACK with OPT_CALLBACK or
OPT_CALLBACK_F where applicable. The heavy lifting was done using the
following (disgusting) shell script:
#!/bin/sh
do_replacement () {
tr '\n' '\r' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\s*0,\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK(\1,\2,\3,\4,\5,\6)/g' |
sed -e 's/{\s*OPTION_CALLBACK,\s*\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\(\s*[^[:space:]}]*\)\s*}/OPT_CALLBACK_F(\1,\2,\3,\4,\5,\6,\7)/g' |
tr '\r' '\n'
}
for f in $(git ls-files \*.c)
do
do_replacement <"$f" >"$f.tmp"
mv "$f.tmp" "$f"
done
The result was manually inspected and then reformatted to match the
style of the surrounding code. Finally, using
`git grep OPTION_CALLBACK \*.c`, leftover results which were not handled
by the script were manually transformed.
Signed-off-by: Denton Liu <liu.denton@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-04-28 08:36:28 +00:00
|
|
|
OPT_CALLBACK(0, CL_ARG__FILTER, fo, N_("args"), \
|
|
|
|
N_("object filtering"), \
|
|
|
|
opt_parse_list_objects_filter)
|
2017-11-21 20:58:50 +00:00
|
|
|
|
2019-01-08 00:17:09 +00:00
|
|
|
/*
|
|
|
|
* Translates abbreviated numbers in the filter's filter_spec into their
|
|
|
|
* fully-expanded forms (e.g., "limit:blob=1k" becomes "limit:blob=1024").
|
2019-06-27 22:54:10 +00:00
|
|
|
* Returns a string owned by the list_objects_filter_options object.
|
2019-01-08 00:17:09 +00:00
|
|
|
*
|
2019-06-27 22:54:10 +00:00
|
|
|
* This form should be used instead of the raw list_objects_filter_spec()
|
|
|
|
* value when communicating with a remote process or subprocess.
|
2019-01-08 00:17:09 +00:00
|
|
|
*/
|
2019-06-27 22:54:10 +00:00
|
|
|
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);
|
2019-01-08 00:17:09 +00:00
|
|
|
|
2017-12-05 16:50:13 +00:00
|
|
|
void list_objects_filter_release(
|
|
|
|
struct list_objects_filter_options *filter_options);
|
|
|
|
|
2017-12-08 15:58:50 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-12-08 15:58:45 +00:00
|
|
|
void partial_clone_register(
|
|
|
|
const char *remote,
|
2019-06-27 22:54:10 +00:00
|
|
|
struct list_objects_filter_options *filter_options);
|
2017-12-08 15:58:45 +00:00
|
|
|
void partial_clone_get_default_filter_spec(
|
2019-06-25 13:40:32 +00:00
|
|
|
struct list_objects_filter_options *filter_options,
|
|
|
|
const char *remote);
|
2017-12-08 15:58:45 +00:00
|
|
|
|
2017-11-21 20:58:50 +00:00
|
|
|
#endif /* LIST_OBJECTS_FILTER_OPTIONS_H */
|