Merge branch 'jc/grep' into next
* jc/grep: builtin-grep: tighten argument parsing.
This commit is contained in:
commit
07c747ee18
@ -494,20 +494,30 @@ static const char builtin_grep_usage[] =
|
|||||||
int cmd_grep(int argc, const char **argv, char **envp)
|
int cmd_grep(int argc, const char **argv, char **envp)
|
||||||
{
|
{
|
||||||
int hit = 0;
|
int hit = 0;
|
||||||
int no_more_flags = 0;
|
|
||||||
int cached = 0;
|
int cached = 0;
|
||||||
|
int seen_dashdash = 0;
|
||||||
struct grep_opt opt;
|
struct grep_opt opt;
|
||||||
struct object_list *list, **tail, *object_list = NULL;
|
struct object_list *list, **tail, *object_list = NULL;
|
||||||
const char *prefix = setup_git_directory();
|
const char *prefix = setup_git_directory();
|
||||||
const char **paths = NULL;
|
const char **paths = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
memset(&opt, 0, sizeof(opt));
|
memset(&opt, 0, sizeof(opt));
|
||||||
opt.pattern_tail = &opt.pattern_list;
|
opt.pattern_tail = &opt.pattern_list;
|
||||||
opt.regflags = REG_NEWLINE;
|
opt.regflags = REG_NEWLINE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No point using rev_info, really.
|
* If there is no -- then the paths must exist in the working
|
||||||
|
* tree. If there is no explicit pattern specified with -e or
|
||||||
|
* -f, we take the first unrecognized non option to be the
|
||||||
|
* pattern, but then what follows it must be zero or more
|
||||||
|
* valid refs up to the -- (if exists), and then existing
|
||||||
|
* paths. If there is an explicit pattern, then the first
|
||||||
|
* unrecocnized non option is the beginning of the refs list
|
||||||
|
* that continues up to the -- (if exists), and then paths.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
tail = &object_list;
|
||||||
while (1 < argc) {
|
while (1 < argc) {
|
||||||
const char *arg = argv[1];
|
const char *arg = argv[1];
|
||||||
argc--; argv++;
|
argc--; argv++;
|
||||||
@ -618,7 +628,7 @@ int cmd_grep(int argc, const char **argv, char **envp)
|
|||||||
usage(builtin_grep_usage);
|
usage(builtin_grep_usage);
|
||||||
patterns = fopen(argv[1], "r");
|
patterns = fopen(argv[1], "r");
|
||||||
if (!patterns)
|
if (!patterns)
|
||||||
die("'%s': %s", strerror(errno));
|
die("'%s': %s", argv[1], strerror(errno));
|
||||||
while (fgets(buf, sizeof(buf), patterns)) {
|
while (fgets(buf, sizeof(buf), patterns)) {
|
||||||
int len = strlen(buf);
|
int len = strlen(buf);
|
||||||
if (buf[len-1] == '\n')
|
if (buf[len-1] == '\n')
|
||||||
@ -642,47 +652,61 @@ int cmd_grep(int argc, const char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
usage(builtin_grep_usage);
|
usage(builtin_grep_usage);
|
||||||
}
|
}
|
||||||
if (!strcmp("--", arg)) {
|
if (!strcmp("--", arg))
|
||||||
no_more_flags = 1;
|
break;
|
||||||
continue;
|
if (*arg == '-')
|
||||||
}
|
|
||||||
/* Either unrecognized option or a single pattern */
|
|
||||||
if (!no_more_flags && *arg == '-')
|
|
||||||
usage(builtin_grep_usage);
|
usage(builtin_grep_usage);
|
||||||
|
|
||||||
|
/* First unrecognized non-option token */
|
||||||
if (!opt.pattern_list) {
|
if (!opt.pattern_list) {
|
||||||
add_pattern(&opt, arg, "command line", 0);
|
add_pattern(&opt, arg, "command line", 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* We are looking at the first path or rev;
|
/* We are looking at the first path or rev;
|
||||||
* it is found at argv[0] after leaving the
|
* it is found at argv[1] after leaving the
|
||||||
* loop.
|
* loop.
|
||||||
*/
|
*/
|
||||||
argc++; argv--;
|
argc++; argv--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opt.pattern_list)
|
if (!opt.pattern_list)
|
||||||
die("no pattern given.");
|
die("no pattern given.");
|
||||||
compile_patterns(&opt);
|
compile_patterns(&opt);
|
||||||
tail = &object_list;
|
|
||||||
while (1 < argc) {
|
/* Check revs and then paths */
|
||||||
struct object *object;
|
for (i = 1; i < argc; i++) {
|
||||||
struct object_list *elem;
|
const char *arg = argv[i];
|
||||||
const char *arg = argv[1];
|
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
if (get_sha1(arg, sha1) < 0)
|
/* Is it a rev? */
|
||||||
break;
|
if (!get_sha1(arg, sha1)) {
|
||||||
object = parse_object(sha1);
|
struct object *object = parse_object(sha1);
|
||||||
|
struct object_list *elem;
|
||||||
if (!object)
|
if (!object)
|
||||||
die("bad object %s", arg);
|
die("bad object %s", arg);
|
||||||
elem = object_list_insert(object, tail);
|
elem = object_list_insert(object, tail);
|
||||||
elem->name = arg;
|
elem->name = arg;
|
||||||
tail = &elem->next;
|
tail = &elem->next;
|
||||||
argc--; argv++;
|
continue;
|
||||||
}
|
}
|
||||||
if (1 < argc)
|
if (!strcmp(arg, "--")) {
|
||||||
paths = get_pathspec(prefix, argv + 1);
|
i++;
|
||||||
|
seen_dashdash = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The rest are paths */
|
||||||
|
if (!seen_dashdash) {
|
||||||
|
int j;
|
||||||
|
for (j = i; j < argc; i++)
|
||||||
|
verify_filename(prefix, argv[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < argc)
|
||||||
|
paths = get_pathspec(prefix, argv + i);
|
||||||
else if (prefix) {
|
else if (prefix) {
|
||||||
paths = xcalloc(2, sizeof(const char *));
|
paths = xcalloc(2, sizeof(const char *));
|
||||||
paths[0] = prefix;
|
paths[0] = prefix;
|
||||||
|
Loading…
Reference in New Issue
Block a user