for-each-ref: add --stdin option
When a user wishes to input a large list of patterns to 'git for-each-ref' (likely a long list of exact refs) there are frequently system limits on the number of command-line arguments. Add a new --stdin option to instead read the patterns from standard input. Add tests that check that any unrecognized arguments are considered an error when --stdin is provided. Also, an empty pattern list is interpreted as the complete ref set. When reading from stdin, we populate the filter.name_patterns array dynamically as opposed to pointing to the 'argv' array directly. This is simple when using a strvec, as it is NULL-terminated in the same way. We then free the memory directly from the strvec. Helped-by: Phillip Wood <phillip.wood123@gmail.com> Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
d15644fe02
commit
b73dec5530
@ -5,6 +5,7 @@
|
||||
#include "object.h"
|
||||
#include "parse-options.h"
|
||||
#include "ref-filter.h"
|
||||
#include "strvec.h"
|
||||
|
||||
static char const * const for_each_ref_usage[] = {
|
||||
N_("git for-each-ref [<options>] [<pattern>]"),
|
||||
@ -25,6 +26,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
||||
struct ref_format format = REF_FORMAT_INIT;
|
||||
struct strbuf output = STRBUF_INIT;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
int from_stdin = 0;
|
||||
struct strvec vec = STRVEC_INIT;
|
||||
|
||||
struct option opts[] = {
|
||||
OPT_BIT('s', "shell", &format.quote_style,
|
||||
@ -49,6 +52,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
||||
OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")),
|
||||
OPT_NO_CONTAINS(&filter.no_commit, N_("print only refs which don't contain the commit")),
|
||||
OPT_BOOL(0, "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
|
||||
OPT_BOOL(0, "stdin", &from_stdin, N_("read reference patterns from stdin")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
@ -75,7 +79,23 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
||||
ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
|
||||
filter.ignore_case = icase;
|
||||
|
||||
filter.name_patterns = argv;
|
||||
if (from_stdin) {
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
|
||||
if (argv[0])
|
||||
die(_("unknown arguments supplied with --stdin"));
|
||||
|
||||
while (strbuf_getline(&line, stdin) != EOF)
|
||||
strvec_push(&vec, line.buf);
|
||||
|
||||
strbuf_release(&line);
|
||||
|
||||
/* vec.v is NULL-terminated, just like 'argv'. */
|
||||
filter.name_patterns = vec.v;
|
||||
} else {
|
||||
filter.name_patterns = argv;
|
||||
}
|
||||
|
||||
filter.match_as_path = 1;
|
||||
filter_refs(&array, &filter, FILTER_REFS_ALL);
|
||||
ref_array_sort(sorting, &array);
|
||||
@ -97,5 +117,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
|
||||
free_commit_list(filter.with_commit);
|
||||
free_commit_list(filter.no_commit);
|
||||
ref_sorting_release(sorting);
|
||||
strvec_clear(&vec);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user