Skip to content

Commit e40b34b

Browse files
committed
Merge branch 'mm/shortopt-detached'
* mm/shortopt-detached: log: parse separate option for --glob log: parse separate options like git log --grep foo diff: parse separate options --stat-width n, --stat-name-width n diff: split off a function for --stat-* option parsing diff: parse separate options like -S foo Conflicts: revision.c
2 parents 613e4e5 + 5adba90 commit e40b34b

File tree

7 files changed

+212
-80
lines changed

7 files changed

+212
-80
lines changed

diff.c

Lines changed: 124 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3002,9 +3002,100 @@ static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *va
30023002

30033003
static int diff_scoreopt_parse(const char *opt);
30043004

3005+
static inline int short_opt(char opt, const char **argv,
3006+
const char **optarg)
3007+
{
3008+
const char *arg = argv[0];
3009+
if (arg[0] != '-' || arg[1] != opt)
3010+
return 0;
3011+
if (arg[2] != '\0') {
3012+
*optarg = arg + 2;
3013+
return 1;
3014+
}
3015+
if (!argv[1])
3016+
die("Option '%c' requires a value", opt);
3017+
*optarg = argv[1];
3018+
return 2;
3019+
}
3020+
3021+
int parse_long_opt(const char *opt, const char **argv,
3022+
const char **optarg)
3023+
{
3024+
const char *arg = argv[0];
3025+
if (arg[0] != '-' || arg[1] != '-')
3026+
return 0;
3027+
arg += strlen("--");
3028+
if (prefixcmp(arg, opt))
3029+
return 0;
3030+
arg += strlen(opt);
3031+
if (*arg == '=') { /* sticked form: --option=value */
3032+
*optarg = arg + 1;
3033+
return 1;
3034+
}
3035+
if (*arg != '\0')
3036+
return 0;
3037+
/* separate form: --option value */
3038+
if (!argv[1])
3039+
die("Option '--%s' requires a value", opt);
3040+
*optarg = argv[1];
3041+
return 2;
3042+
}
3043+
3044+
static int stat_opt(struct diff_options *options, const char **av)
3045+
{
3046+
const char *arg = av[0];
3047+
char *end;
3048+
int width = options->stat_width;
3049+
int name_width = options->stat_name_width;
3050+
int argcount = 1;
3051+
3052+
arg += strlen("--stat");
3053+
end = (char *)arg;
3054+
3055+
switch (*arg) {
3056+
case '-':
3057+
if (!prefixcmp(arg, "-width")) {
3058+
arg += strlen("-width");
3059+
if (*arg == '=')
3060+
width = strtoul(arg + 1, &end, 10);
3061+
else if (!*arg && !av[1])
3062+
die("Option '--stat-width' requires a value");
3063+
else if (!*arg) {
3064+
width = strtoul(av[1], &end, 10);
3065+
argcount = 2;
3066+
}
3067+
} else if (!prefixcmp(arg, "-name-width")) {
3068+
arg += strlen("-name-width");
3069+
if (*arg == '=')
3070+
name_width = strtoul(arg + 1, &end, 10);
3071+
else if (!*arg && !av[1])
3072+
die("Option '--stat-name-width' requires a value");
3073+
else if (!*arg) {
3074+
name_width = strtoul(av[1], &end, 10);
3075+
argcount = 2;
3076+
}
3077+
}
3078+
break;
3079+
case '=':
3080+
width = strtoul(arg+1, &end, 10);
3081+
if (*end == ',')
3082+
name_width = strtoul(end+1, &end, 10);
3083+
}
3084+
3085+
/* Important! This checks all the error cases! */
3086+
if (*end)
3087+
return 0;
3088+
options->output_format |= DIFF_FORMAT_DIFFSTAT;
3089+
options->stat_name_width = name_width;
3090+
options->stat_width = width;
3091+
return argcount;
3092+
}
3093+
30053094
int diff_opt_parse(struct diff_options *options, const char **av, int ac)
30063095
{
30073096
const char *arg = av[0];
3097+
const char *optarg;
3098+
int argcount;
30083099

30093100
/* Output format options */
30103101
if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch"))
@@ -3041,33 +3132,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
30413132
options->output_format |= DIFF_FORMAT_NAME_STATUS;
30423133
else if (!strcmp(arg, "-s"))
30433134
options->output_format |= DIFF_FORMAT_NO_OUTPUT;
3044-
else if (!prefixcmp(arg, "--stat")) {
3045-
char *end;
3046-
int width = options->stat_width;
3047-
int name_width = options->stat_name_width;
3048-
arg += 6;
3049-
end = (char *)arg;
3050-
3051-
switch (*arg) {
3052-
case '-':
3053-
if (!prefixcmp(arg, "-width="))
3054-
width = strtoul(arg + 7, &end, 10);
3055-
else if (!prefixcmp(arg, "-name-width="))
3056-
name_width = strtoul(arg + 12, &end, 10);
3057-
break;
3058-
case '=':
3059-
width = strtoul(arg+1, &end, 10);
3060-
if (*end == ',')
3061-
name_width = strtoul(end+1, &end, 10);
3062-
}
3063-
3064-
/* Important! This checks all the error cases! */
3065-
if (*end)
3066-
return 0;
3067-
options->output_format |= DIFF_FORMAT_DIFFSTAT;
3068-
options->stat_name_width = name_width;
3069-
options->stat_width = width;
3070-
}
3135+
else if (!prefixcmp(arg, "--stat"))
3136+
/* --stat, --stat-width, or --stat-name-width */
3137+
return stat_opt(options, av);
30713138

30723139
/* renames options */
30733140
else if (!prefixcmp(arg, "-B")) {
@@ -3161,10 +3228,11 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
31613228
else
31623229
die("bad --word-diff argument: %s", type);
31633230
}
3164-
else if (!prefixcmp(arg, "--word-diff-regex=")) {
3231+
else if ((argcount = parse_long_opt("word-diff-regex", av, &optarg))) {
31653232
if (options->word_diff == DIFF_WORDS_NONE)
31663233
options->word_diff = DIFF_WORDS_PLAIN;
3167-
options->word_regex = arg + 18;
3234+
options->word_regex = optarg;
3235+
return argcount;
31683236
}
31693237
else if (!strcmp(arg, "--exit-code"))
31703238
DIFF_OPT_SET(options, EXIT_WITH_STATUS);
@@ -3194,18 +3262,26 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
31943262
/* misc options */
31953263
else if (!strcmp(arg, "-z"))
31963264
options->line_termination = 0;
3197-
else if (!prefixcmp(arg, "-l"))
3198-
options->rename_limit = strtoul(arg+2, NULL, 10);
3199-
else if (!prefixcmp(arg, "-S"))
3200-
options->pickaxe = arg + 2;
3265+
else if ((argcount = short_opt('l', av, &optarg))) {
3266+
options->rename_limit = strtoul(optarg, NULL, 10);
3267+
return argcount;
3268+
}
3269+
else if ((argcount = short_opt('S', av, &optarg))) {
3270+
options->pickaxe = optarg;
3271+
return argcount;
3272+
}
32013273
else if (!strcmp(arg, "--pickaxe-all"))
32023274
options->pickaxe_opts = DIFF_PICKAXE_ALL;
32033275
else if (!strcmp(arg, "--pickaxe-regex"))
32043276
options->pickaxe_opts = DIFF_PICKAXE_REGEX;
3205-
else if (!prefixcmp(arg, "-O"))
3206-
options->orderfile = arg + 2;
3207-
else if (!prefixcmp(arg, "--diff-filter="))
3208-
options->filter = arg + 14;
3277+
else if ((argcount = short_opt('O', av, &optarg))) {
3278+
options->orderfile = optarg;
3279+
return argcount;
3280+
}
3281+
else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
3282+
options->filter = optarg;
3283+
return argcount;
3284+
}
32093285
else if (!strcmp(arg, "--abbrev"))
32103286
options->abbrev = DEFAULT_ABBREV;
32113287
else if (!prefixcmp(arg, "--abbrev=")) {
@@ -3215,20 +3291,25 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
32153291
else if (40 < options->abbrev)
32163292
options->abbrev = 40;
32173293
}
3218-
else if (!prefixcmp(arg, "--src-prefix="))
3219-
options->a_prefix = arg + 13;
3220-
else if (!prefixcmp(arg, "--dst-prefix="))
3221-
options->b_prefix = arg + 13;
3294+
else if ((argcount = parse_long_opt("src-prefix", av, &optarg))) {
3295+
options->a_prefix = optarg;
3296+
return argcount;
3297+
}
3298+
else if ((argcount = parse_long_opt("dst-prefix", av, &optarg))) {
3299+
options->b_prefix = optarg;
3300+
return argcount;
3301+
}
32223302
else if (!strcmp(arg, "--no-prefix"))
32233303
options->a_prefix = options->b_prefix = "";
32243304
else if (opt_arg(arg, '\0', "inter-hunk-context",
32253305
&options->interhunkcontext))
32263306
;
3227-
else if (!prefixcmp(arg, "--output=")) {
3228-
options->file = fopen(arg + strlen("--output="), "w");
3307+
else if ((argcount = parse_long_opt("output", av, &optarg))) {
3308+
options->file = fopen(optarg, "w");
32293309
if (!options->file)
32303310
die_errno("Could not open '%s'", arg + strlen("--output="));
32313311
options->close_file = 1;
3312+
return argcount;
32323313
} else
32333314
return 0;
32343315
return 1;

diff.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,13 @@ extern void diff_unmerge(struct diff_options *,
218218
#define DIFF_SETUP_USE_CACHE 2
219219
#define DIFF_SETUP_USE_SIZE_CACHE 4
220220

221+
/*
222+
* Poor man's alternative to parse-option, to allow both sticked form
223+
* (--option=value) and separate form (--option value).
224+
*/
225+
extern int parse_long_opt(const char *opt, const char **argv,
226+
const char **optarg);
227+
221228
extern int git_diff_basic_config(const char *var, const char *value, void *cb);
222229
extern int git_diff_ui_config(const char *var, const char *value, void *cb);
223230
extern int diff_use_color_default;

revision.c

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
11481148
int *unkc, const char **unkv)
11491149
{
11501150
const char *arg = argv[0];
1151+
const char *optarg;
1152+
int argcount;
11511153

11521154
/* pseudo revision arguments */
11531155
if (!strcmp(arg, "--all") || !strcmp(arg, "--branches") ||
@@ -1160,11 +1162,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
11601162
return 1;
11611163
}
11621164

1163-
if (!prefixcmp(arg, "--max-count=")) {
1164-
revs->max_count = atoi(arg + 12);
1165+
if ((argcount = parse_long_opt("max-count", argv, &optarg))) {
1166+
revs->max_count = atoi(optarg);
11651167
revs->no_walk = 0;
1166-
} else if (!prefixcmp(arg, "--skip=")) {
1167-
revs->skip_count = atoi(arg + 7);
1168+
return argcount;
1169+
} else if ((argcount = parse_long_opt("skip", argv, &optarg))) {
1170+
revs->skip_count = atoi(optarg);
1171+
return argcount;
11681172
} else if ((*arg == '-') && isdigit(arg[1])) {
11691173
/* accept -<digit>, like traditional "head" */
11701174
revs->max_count = atoi(arg + 1);
@@ -1178,18 +1182,24 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
11781182
} else if (!prefixcmp(arg, "-n")) {
11791183
revs->max_count = atoi(arg + 2);
11801184
revs->no_walk = 0;
1181-
} else if (!prefixcmp(arg, "--max-age=")) {
1182-
revs->max_age = atoi(arg + 10);
1183-
} else if (!prefixcmp(arg, "--since=")) {
1184-
revs->max_age = approxidate(arg + 8);
1185-
} else if (!prefixcmp(arg, "--after=")) {
1186-
revs->max_age = approxidate(arg + 8);
1187-
} else if (!prefixcmp(arg, "--min-age=")) {
1188-
revs->min_age = atoi(arg + 10);
1189-
} else if (!prefixcmp(arg, "--before=")) {
1190-
revs->min_age = approxidate(arg + 9);
1191-
} else if (!prefixcmp(arg, "--until=")) {
1192-
revs->min_age = approxidate(arg + 8);
1185+
} else if ((argcount = parse_long_opt("max-age", argv, &optarg))) {
1186+
revs->max_age = atoi(optarg);
1187+
return argcount;
1188+
} else if ((argcount = parse_long_opt("since", argv, &optarg))) {
1189+
revs->max_age = approxidate(optarg);
1190+
return argcount;
1191+
} else if ((argcount = parse_long_opt("after", argv, &optarg))) {
1192+
revs->max_age = approxidate(optarg);
1193+
return argcount;
1194+
} else if ((argcount = parse_long_opt("min-age", argv, &optarg))) {
1195+
revs->min_age = atoi(optarg);
1196+
return argcount;
1197+
} else if ((argcount = parse_long_opt("before", argv, &optarg))) {
1198+
revs->min_age = approxidate(optarg);
1199+
return argcount;
1200+
} else if ((argcount = parse_long_opt("until", argv, &optarg))) {
1201+
revs->min_age = approxidate(optarg);
1202+
return argcount;
11931203
} else if (!strcmp(arg, "--first-parent")) {
11941204
revs->first_parent_only = 1;
11951205
} else if (!strcmp(arg, "--ancestry-path")) {
@@ -1295,6 +1305,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
12951305
revs->pretty_given = 1;
12961306
get_commit_format(arg+8, revs);
12971307
} else if (!prefixcmp(arg, "--pretty=") || !prefixcmp(arg, "--format=")) {
1308+
/*
1309+
* Detached form ("--pretty X" as opposed to "--pretty=X")
1310+
* not allowed, since the argument is optional.
1311+
*/
12981312
revs->verbose_header = 1;
12991313
revs->pretty_given = 1;
13001314
get_commit_format(arg+9, revs);
@@ -1359,21 +1373,25 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
13591373
} else if (!strcmp(arg, "--relative-date")) {
13601374
revs->date_mode = DATE_RELATIVE;
13611375
revs->date_mode_explicit = 1;
1362-
} else if (!strncmp(arg, "--date=", 7)) {
1363-
revs->date_mode = parse_date_format(arg + 7);
1376+
} else if ((argcount = parse_long_opt("date", argv, &optarg))) {
1377+
revs->date_mode = parse_date_format(optarg);
13641378
revs->date_mode_explicit = 1;
1379+
return argcount;
13651380
} else if (!strcmp(arg, "--log-size")) {
13661381
revs->show_log_size = 1;
13671382
}
13681383
/*
13691384
* Grepping the commit log
13701385
*/
1371-
else if (!prefixcmp(arg, "--author=")) {
1372-
add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);
1373-
} else if (!prefixcmp(arg, "--committer=")) {
1374-
add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);
1375-
} else if (!prefixcmp(arg, "--grep=")) {
1376-
add_message_grep(revs, arg+7);
1386+
else if ((argcount = parse_long_opt("author", argv, &optarg))) {
1387+
add_header_grep(revs, GREP_HEADER_AUTHOR, optarg);
1388+
return argcount;
1389+
} else if ((argcount = parse_long_opt("committer", argv, &optarg))) {
1390+
add_header_grep(revs, GREP_HEADER_COMMITTER, optarg);
1391+
return argcount;
1392+
} else if ((argcount = parse_long_opt("grep", argv, &optarg))) {
1393+
add_message_grep(revs, optarg);
1394+
return argcount;
13771395
} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
13781396
revs->grep_filter.regflags |= REG_EXTENDED;
13791397
} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
@@ -1382,12 +1400,12 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
13821400
revs->grep_filter.fixed = 1;
13831401
} else if (!strcmp(arg, "--all-match")) {
13841402
revs->grep_filter.all_match = 1;
1385-
} else if (!prefixcmp(arg, "--encoding=")) {
1386-
arg += 11;
1387-
if (strcmp(arg, "none"))
1388-
git_log_output_encoding = xstrdup(arg);
1403+
} else if ((argcount = parse_long_opt("encoding", argv, &optarg))) {
1404+
if (strcmp(optarg, "none"))
1405+
git_log_output_encoding = xstrdup(optarg);
13891406
else
13901407
git_log_output_encoding = "";
1408+
return argcount;
13911409
} else if (!strcmp(arg, "--reverse")) {
13921410
revs->reverse ^= 1;
13931411
} else if (!strcmp(arg, "--children")) {
@@ -1467,6 +1485,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
14671485
int i, flags, left, seen_dashdash, read_from_stdin, got_rev_arg = 0;
14681486
const char **prune_data = NULL;
14691487
const char *submodule = NULL;
1488+
const char *optarg;
1489+
int argcount;
14701490

14711491
if (opt)
14721492
submodule = opt->submodule;
@@ -1516,10 +1536,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
15161536
handle_refs(submodule, revs, flags, for_each_remote_ref_submodule);
15171537
continue;
15181538
}
1519-
if (!prefixcmp(arg, "--glob=")) {
1539+
if ((argcount = parse_long_opt("glob", argv + i, &optarg))) {
15201540
struct all_refs_cb cb;
1541+
i += argcount - 1;
15211542
init_all_refs_cb(&cb, revs, flags);
1522-
for_each_glob_ref(handle_one_ref, arg + 7, &cb);
1543+
for_each_glob_ref(handle_one_ref, optarg, &cb);
15231544
continue;
15241545
}
15251546
if (!prefixcmp(arg, "--branches=")) {

t/t4013-diff-various.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ log -p --first-parent master
208208
log -m -p --first-parent master
209209
log -m -p master
210210
log -SF master
211+
log -S F master
211212
log -SF -p master
212213
log --decorate --all
213214
log --decorate=full --all
@@ -282,4 +283,8 @@ diff master master^ side
282283
diff --dirstat master~1 master~2
283284
EOF
284285

286+
test_expect_success 'log -S requires an argument' '
287+
test_must_fail git log -S
288+
'
289+
285290
test_done

0 commit comments

Comments
 (0)