Skip to content

Commit c4bf868

Browse files
committed
Merge branch 'jc/revision-parse-int'
The command line parser for the "log" family of commands was too loose when parsing certain numbers, e.g., silently ignoring the extra 'q' in "git log -n 1q" without complaining, which has been tightened up. * jc/revision-parse-int: revision: parse integer arguments to --max-count, --skip, etc., more carefully
2 parents 2d09302 + 71a1e94 commit c4bf868

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed

revision.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,6 +2223,27 @@ static void add_message_grep(struct rev_info *revs, const char *pattern)
22232223
add_grep(revs, pattern, GREP_PATTERN_BODY);
22242224
}
22252225

2226+
static int parse_count(const char *arg)
2227+
{
2228+
int count;
2229+
2230+
if (strtol_i(arg, 10, &count) < 0)
2231+
die("'%s': not an integer", arg);
2232+
return count;
2233+
}
2234+
2235+
static timestamp_t parse_age(const char *arg)
2236+
{
2237+
timestamp_t num;
2238+
char *p;
2239+
2240+
errno = 0;
2241+
num = parse_timestamp(arg, &p, 10);
2242+
if (errno || *p || p == arg)
2243+
die("'%s': not a number of seconds since epoch", arg);
2244+
return num;
2245+
}
2246+
22262247
static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
22272248
int *unkc, const char **unkv,
22282249
const struct setup_revision_opt* opt)
@@ -2249,29 +2270,27 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
22492270
}
22502271

22512272
if ((argcount = parse_long_opt("max-count", argv, &optarg))) {
2252-
revs->max_count = atoi(optarg);
2273+
revs->max_count = parse_count(optarg);
22532274
revs->no_walk = 0;
22542275
return argcount;
22552276
} else if ((argcount = parse_long_opt("skip", argv, &optarg))) {
2256-
revs->skip_count = atoi(optarg);
2277+
revs->skip_count = parse_count(optarg);
22572278
return argcount;
22582279
} else if ((*arg == '-') && isdigit(arg[1])) {
22592280
/* accept -<digit>, like traditional "head" */
2260-
if (strtol_i(arg + 1, 10, &revs->max_count) < 0 ||
2261-
revs->max_count < 0)
2262-
die("'%s': not a non-negative integer", arg + 1);
2281+
revs->max_count = parse_count(arg + 1);
22632282
revs->no_walk = 0;
22642283
} else if (!strcmp(arg, "-n")) {
22652284
if (argc <= 1)
22662285
return error("-n requires an argument");
2267-
revs->max_count = atoi(argv[1]);
2286+
revs->max_count = parse_count(argv[1]);
22682287
revs->no_walk = 0;
22692288
return 2;
22702289
} else if (skip_prefix(arg, "-n", &optarg)) {
2271-
revs->max_count = atoi(optarg);
2290+
revs->max_count = parse_count(optarg);
22722291
revs->no_walk = 0;
22732292
} else if ((argcount = parse_long_opt("max-age", argv, &optarg))) {
2274-
revs->max_age = atoi(optarg);
2293+
revs->max_age = parse_age(optarg);
22752294
return argcount;
22762295
} else if ((argcount = parse_long_opt("since", argv, &optarg))) {
22772296
revs->max_age = approxidate(optarg);
@@ -2283,7 +2302,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
22832302
revs->max_age = approxidate(optarg);
22842303
return argcount;
22852304
} else if ((argcount = parse_long_opt("min-age", argv, &optarg))) {
2286-
revs->min_age = atoi(optarg);
2305+
revs->min_age = parse_age(optarg);
22872306
return argcount;
22882307
} else if ((argcount = parse_long_opt("before", argv, &optarg))) {
22892308
revs->min_age = approxidate(optarg);
@@ -2371,11 +2390,11 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
23712390
} else if (!strcmp(arg, "--no-merges")) {
23722391
revs->max_parents = 1;
23732392
} else if (skip_prefix(arg, "--min-parents=", &optarg)) {
2374-
revs->min_parents = atoi(optarg);
2393+
revs->min_parents = parse_count(optarg);
23752394
} else if (!strcmp(arg, "--no-min-parents")) {
23762395
revs->min_parents = 0;
23772396
} else if (skip_prefix(arg, "--max-parents=", &optarg)) {
2378-
revs->max_parents = atoi(optarg);
2397+
revs->max_parents = parse_count(optarg);
23792398
} else if (!strcmp(arg, "--no-max-parents")) {
23802399
revs->max_parents = -1;
23812400
} else if (!strcmp(arg, "--boundary")) {

t/t6005-rev-list-count.sh

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,34 @@ test_expect_success 'no options' '
1818
'
1919

2020
test_expect_success '--max-count' '
21+
test_must_fail git rev-list --max-count=1q HEAD 2>error &&
22+
grep "not an integer" error &&
23+
2124
test_stdout_line_count = 0 git rev-list HEAD --max-count=0 &&
2225
test_stdout_line_count = 3 git rev-list HEAD --max-count=3 &&
2326
test_stdout_line_count = 5 git rev-list HEAD --max-count=5 &&
24-
test_stdout_line_count = 5 git rev-list HEAD --max-count=10
27+
test_stdout_line_count = 5 git rev-list HEAD --max-count=10 &&
28+
test_stdout_line_count = 5 git rev-list HEAD --max-count=-1
2529
'
2630

2731
test_expect_success '--max-count all forms' '
32+
test_must_fail git rev-list -1q HEAD 2>error &&
33+
grep "not an integer" error &&
34+
test_must_fail git rev-list --1 HEAD &&
35+
test_must_fail git rev-list -n 1q HEAD 2>error &&
36+
grep "not an integer" error &&
37+
2838
test_stdout_line_count = 1 git rev-list HEAD --max-count=1 &&
2939
test_stdout_line_count = 1 git rev-list HEAD -1 &&
3040
test_stdout_line_count = 1 git rev-list HEAD -n1 &&
31-
test_stdout_line_count = 1 git rev-list HEAD -n 1
41+
test_stdout_line_count = 1 git rev-list HEAD -n 1 &&
42+
test_stdout_line_count = 5 git rev-list HEAD -n -1
3243
'
3344

3445
test_expect_success '--skip' '
46+
test_must_fail git rev-list --skip 1q HEAD 2>error &&
47+
grep "not an integer" error &&
48+
3549
test_stdout_line_count = 5 git rev-list HEAD --skip=0 &&
3650
test_stdout_line_count = 2 git rev-list HEAD --skip=3 &&
3751
test_stdout_line_count = 0 git rev-list HEAD --skip=5 &&

t/t6009-rev-list-parent.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ test_expect_success 'setup roots, merges and octopuses' '
6363
git checkout main
6464
'
6565

66+
test_expect_success 'parse --max-parents & --min-parents' '
67+
test_must_fail git rev-list --max-parents=1q HEAD 2>error &&
68+
grep "not an integer" error &&
69+
70+
test_must_fail git rev-list --min-parents=1q HEAD 2>error &&
71+
grep "not an integer" error &&
72+
73+
git rev-list --max-parents=1 --min-parents=1 HEAD &&
74+
git rev-list --max-parents=-1 --min-parents=-1 HEAD
75+
'
76+
6677
test_expect_success 'rev-list roots' '
6778
6879
check_revlist "--max-parents=0" one five

0 commit comments

Comments
 (0)