From 1987b0b20f7b29a25260fd25f907121d22b18b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Thu, 17 Jan 2019 20:05:00 +0700 Subject: parse-options.h: remove extern on function prototypes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/parse-options.h b/parse-options.h index 14fe324..f5e7ec7 100644 --- a/parse-options.h +++ b/parse-options.h @@ -174,18 +174,18 @@ struct option { * for translation with N_(). * Returns the number of arguments left in argv[]. */ -extern int parse_options(int argc, const char **argv, const char *prefix, - const struct option *options, - const char * const usagestr[], int flags); +int parse_options(int argc, const char **argv, const char *prefix, + const struct option *options, + const char * const usagestr[], int flags); -extern NORETURN void usage_with_options(const char * const *usagestr, - const struct option *options); +NORETURN void usage_with_options(const char * const *usagestr, + const struct option *options); -extern NORETURN void usage_msg_opt(const char *msg, - const char * const *usagestr, - const struct option *options); +NORETURN void usage_msg_opt(const char *msg, + const char * const *usagestr, + const struct option *options); -extern int optbug(const struct option *opt, const char *reason); +int optbug(const struct option *opt, const char *reason); const char *optname(const struct option *opt, int flags); /* @@ -227,31 +227,31 @@ struct parse_opt_ctx_t { const char *prefix; }; -extern void parse_options_start(struct parse_opt_ctx_t *ctx, - int argc, const char **argv, const char *prefix, - const struct option *options, int flags); +void parse_options_start(struct parse_opt_ctx_t *ctx, + int argc, const char **argv, const char *prefix, + const struct option *options, int flags); -extern int parse_options_step(struct parse_opt_ctx_t *ctx, - const struct option *options, - const char * const usagestr[]); +int parse_options_step(struct parse_opt_ctx_t *ctx, + const struct option *options, + const char * const usagestr[]); -extern int parse_options_end(struct parse_opt_ctx_t *ctx); +int parse_options_end(struct parse_opt_ctx_t *ctx); -extern struct option *parse_options_concat(struct option *a, struct option *b); +struct option *parse_options_concat(struct option *a, struct option *b); /*----- some often used options -----*/ -extern int parse_opt_abbrev_cb(const struct option *, const char *, int); -extern int parse_opt_expiry_date_cb(const struct option *, const char *, int); -extern int parse_opt_color_flag_cb(const struct option *, const char *, int); -extern int parse_opt_verbosity_cb(const struct option *, const char *, int); -extern int parse_opt_object_name(const struct option *, const char *, int); -extern int parse_opt_commits(const struct option *, const char *, int); -extern int parse_opt_tertiary(const struct option *, const char *, int); -extern int parse_opt_string_list(const struct option *, const char *, int); -extern int parse_opt_noop_cb(const struct option *, const char *, int); -extern int parse_opt_unknown_cb(const struct option *, const char *, int); -extern int parse_opt_passthru(const struct option *, const char *, int); -extern int parse_opt_passthru_argv(const struct option *, const char *, int); +int parse_opt_abbrev_cb(const struct option *, const char *, int); +int parse_opt_expiry_date_cb(const struct option *, const char *, int); +int parse_opt_color_flag_cb(const struct option *, const char *, int); +int parse_opt_verbosity_cb(const struct option *, const char *, int); +int parse_opt_object_name(const struct option *, const char *, int); +int parse_opt_commits(const struct option *, const char *, int); +int parse_opt_tertiary(const struct option *, const char *, int); +int parse_opt_string_list(const struct option *, const char *, int); +int parse_opt_noop_cb(const struct option *, const char *, int); +int parse_opt_unknown_cb(const struct option *, const char *, int); +int parse_opt_passthru(const struct option *, const char *, int); +int parse_opt_passthru_argv(const struct option *, const char *, int); #define OPT__VERBOSE(var, h) OPT_COUNTUP('v', "verbose", (var), (h)) #define OPT__QUIET(var, h) OPT_COUNTUP('q', "quiet", (var), (h)) -- cgit v0.10.2-6-g49f6 From 202fbb33156287feeabc39c46db0e9857cb97152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:23 +0700 Subject: parse-options: add one-shot mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to help reimplement diff_opt_parse() using parse_options(). The behavior of parse_options() is changed to be the same as the other: - no argv0 in argv[], everything can be processed - argv[] must not be updated, it's the caller's job to do that - return the number of arguments processed - leave all unknown options / non-options alone (this one can already be achieved with PARSE_OPT_KEEP_UNKNOWN and PARSE_OPT_STOP_AT_NON_OPTION) This mode is NOT supposed to stay here for long. It's to help converting diff/rev option parsing. Once that work is over and we can just use parse_options() throughout the code base, this will be deleted. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/parse-options.c b/parse-options.c index 9f84bac..740ae54 100644 --- a/parse-options.c +++ b/parse-options.c @@ -416,15 +416,24 @@ void parse_options_start(struct parse_opt_ctx_t *ctx, const struct option *options, int flags) { memset(ctx, 0, sizeof(*ctx)); - ctx->argc = ctx->total = argc - 1; - ctx->argv = argv + 1; - ctx->out = argv; + ctx->argc = argc; + ctx->argv = argv; + if (!(flags & PARSE_OPT_ONE_SHOT)) { + ctx->argc--; + ctx->argv++; + } + ctx->total = ctx->argc; + ctx->out = argv; ctx->prefix = prefix; ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0); ctx->flags = flags; if ((flags & PARSE_OPT_KEEP_UNKNOWN) && - (flags & PARSE_OPT_STOP_AT_NON_OPTION)) + (flags & PARSE_OPT_STOP_AT_NON_OPTION) && + !(flags & PARSE_OPT_ONE_SHOT)) BUG("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together"); + if ((flags & PARSE_OPT_ONE_SHOT) && + (flags & PARSE_OPT_KEEP_ARGV0)) + BUG("Can't keep argv0 if you don't have it"); parse_options_check(options); } @@ -536,6 +545,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, for (; ctx->argc; ctx->argc--, ctx->argv++) { const char *arg = ctx->argv[0]; + if (ctx->flags & PARSE_OPT_ONE_SHOT && + ctx->argc != ctx->total) + break; + if (*arg != '-' || !arg[1]) { if (parse_nodash_opt(ctx, arg, options) == 0) continue; @@ -610,6 +623,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, } continue; unknown: + if (ctx->flags & PARSE_OPT_ONE_SHOT) + break; if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN)) return PARSE_OPT_UNKNOWN; ctx->out[ctx->cpidx++] = ctx->argv[0]; @@ -623,6 +638,9 @@ unknown: int parse_options_end(struct parse_opt_ctx_t *ctx) { + if (ctx->flags & PARSE_OPT_ONE_SHOT) + return ctx->total - ctx->argc; + MOVE_ARRAY(ctx->out + ctx->cpidx, ctx->argv, ctx->argc); ctx->out[ctx->cpidx + ctx->argc] = NULL; return ctx->cpidx + ctx->argc; diff --git a/parse-options.h b/parse-options.h index f5e7ec7..d663b83 100644 --- a/parse-options.h +++ b/parse-options.h @@ -27,7 +27,8 @@ enum parse_opt_flags { PARSE_OPT_STOP_AT_NON_OPTION = 2, PARSE_OPT_KEEP_ARGV0 = 4, PARSE_OPT_KEEP_UNKNOWN = 8, - PARSE_OPT_NO_INTERNAL_HELP = 16 + PARSE_OPT_NO_INTERNAL_HELP = 16, + PARSE_OPT_ONE_SHOT = 32 }; enum parse_opt_option_flags { @@ -169,10 +170,18 @@ struct option { N_("no-op (backward compatibility)"), \ PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, parse_opt_noop_cb } -/* parse_options() will filter out the processed options and leave the - * non-option arguments in argv[]. usagestr strings should be marked - * for translation with N_(). +/* + * parse_options() will filter out the processed options and leave the + * non-option arguments in argv[]. argv0 is assumed program name and + * skipped. + * + * usagestr strings should be marked for translation with N_(). + * * Returns the number of arguments left in argv[]. + * + * In one-shot mode, argv0 is not a program name, argv[] is left + * untouched and parse_options() returns the number of options + * processed. */ int parse_options(int argc, const char **argv, const char *prefix, const struct option *options, -- cgit v0.10.2-6-g49f6 From baa4adc66aefe2c3cc15b573b8a19dec786a1641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:24 +0700 Subject: parse-options: disable option abbreviation with PARSE_OPT_KEEP_UNKNOWN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse-options can unambiguously find an abbreviation only if it sees all available options. This is usually the case when you use parse_options(). But there are other callers like blame or shortlog which uses parse_options_start() in combination with a custom option parser, like rev-list. parse-options cannot see all options in this case and will get abbrev detection wrong. Disable it. t7800 needs update because --symlink no longer expands to --symlinks and will be passed down to git-diff, which will not recognize it. I still think this is the correct thing to do. But if --symlink has been actually used in the wild, we would just add an option alias for it. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/parse-options.c b/parse-options.c index 740ae54..779034e 100644 --- a/parse-options.c +++ b/parse-options.c @@ -266,7 +266,8 @@ again: } if (!rest) { /* abbreviated? */ - if (!strncmp(long_name, arg, arg_end - arg)) { + if (!(p->flags & PARSE_OPT_KEEP_UNKNOWN) && + !strncmp(long_name, arg, arg_end - arg)) { is_abbreviated: if (abbrev_option) { /* diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 22b9199..bb9a7f4 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -546,7 +546,7 @@ do done >actual EOF -test_expect_success SYMLINKS 'difftool --dir-diff --symlink without unstaged changes' ' +test_expect_success SYMLINKS 'difftool --dir-diff --symlinks without unstaged changes' ' cat >expect <<-EOF && file $PWD/file @@ -555,7 +555,7 @@ test_expect_success SYMLINKS 'difftool --dir-diff --symlink without unstaged cha sub/sub $PWD/sub/sub EOF - git difftool --dir-diff --symlink \ + git difftool --dir-diff --symlinks \ --extcmd "./.git/CHECK_SYMLINKS" branch HEAD && test_cmp expect actual ' -- cgit v0.10.2-6-g49f6 From f62470c650e0db9536f32b9e1ecbe7d25f759031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:25 +0700 Subject: parse-options: add OPT_BITOP() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed for diff_opt_parse() where we do value = (value & ~mask) | some_more; Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/parse-options.c b/parse-options.c index 779034e..62d94ca 100644 --- a/parse-options.c +++ b/parse-options.c @@ -109,6 +109,13 @@ static int get_value(struct parse_opt_ctx_t *p, *(int *)opt->value &= ~opt->defval; return 0; + case OPTION_BITOP: + if (unset) + BUG("BITOP can't have unset form"); + *(int *)opt->value &= ~opt->extra; + *(int *)opt->value |= opt->defval; + return 0; + case OPTION_COUNTUP: if (*(int *)opt->value < 0) *(int *)opt->value = 0; diff --git a/parse-options.h b/parse-options.h index d663b83..c97324f 100644 --- a/parse-options.h +++ b/parse-options.h @@ -10,6 +10,7 @@ enum parse_opt_type { /* options with no arguments */ OPTION_BIT, OPTION_NEGBIT, + OPTION_BITOP, OPTION_COUNTUP, OPTION_SET_INT, OPTION_CMDMODE, @@ -118,6 +119,7 @@ struct option { int flags; parse_opt_cb *callback; intptr_t defval; + intptr_t extra; }; #define OPT_BIT_F(s, l, v, h, b, f) { OPTION_BIT, (s), (l), (v), NULL, (h), \ @@ -133,6 +135,9 @@ struct option { (h), PARSE_OPT_NOARG} #define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } #define OPT_BIT(s, l, v, h, b) OPT_BIT_F(s, l, v, h, b, 0) +#define OPT_BITOP(s, l, v, h, set, clear) { OPTION_BITOP, (s), (l), (v), NULL, (h), \ + PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, \ + (set), (clear) } #define OPT_NEGBIT(s, l, v, h, b) { OPTION_NEGBIT, (s), (l), (v), NULL, \ (h), PARSE_OPT_NOARG, NULL, (b) } #define OPT_COUNTUP(s, l, v, h) OPT_COUNTUP_F(s, l, v, h, 0) -- cgit v0.10.2-6-g49f6 From bf3ff338a25b7353ec6d39d31e14d081be9e3471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:26 +0700 Subject: parse-options: stop abusing 'callback' for lowlevel callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lowlevel callbacks have different function signatures. Add a new field in 'struct option' with the right type for lowlevel callbacks. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/builtin/blame.c b/builtin/blame.c index 6d798f9..8dcc55d 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -814,7 +814,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) * and are only included here to get included in the "-h" * output: */ - { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, parse_opt_unknown_cb }, + { OPTION_LOWLEVEL_CALLBACK, 0, "indent-heuristic", NULL, NULL, N_("Use an experimental heuristic to improve diffs"), PARSE_OPT_NOARG, NULL, 0, parse_opt_unknown_cb }, OPT_BIT(0, "minimal", &xdl_opts, N_("Spend extra cycles to find better match"), XDF_NEED_MINIMAL), OPT_STRING('S', NULL, &revs_file, N_("file"), N_("Use revisions from instead of calling git-rev-list")), diff --git a/builtin/merge.c b/builtin/merge.c index dc0b7cc..07839b0 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -261,7 +261,7 @@ static struct option builtin_merge_options[] = { option_parse_message), { OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"), N_("read message from file"), PARSE_OPT_NONEG, - (parse_opt_cb *) option_read_message }, + NULL, 0, option_read_message }, OPT__VERBOSITY(&verbosity), OPT_BOOL(0, "abort", &abort_current_merge, N_("abort the current in-progress merge")), diff --git a/builtin/update-index.c b/builtin/update-index.c index e19da77..727a811 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -985,7 +985,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) N_("add the specified entry to the index"), PARSE_OPT_NOARG | /* disallow --cacheinfo= form */ PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, - (parse_opt_cb *) cacheinfo_callback}, + NULL, 0, + cacheinfo_callback}, {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, "(+|-)x", N_("override the executable bit of the listed files"), PARSE_OPT_NONEG, @@ -1011,19 +1012,19 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL, N_("read list of paths to be updated from standard input"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) stdin_callback}, + NULL, 0, stdin_callback}, {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL, N_("add entries from standard input to the index"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) stdin_cacheinfo_callback}, + NULL, 0, stdin_cacheinfo_callback}, {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL, N_("repopulate stages #2 and #3 for the listed paths"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) unresolve_callback}, + NULL, 0, unresolve_callback}, {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL, N_("only update entries that differ from HEAD"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) reupdate_callback}, + NULL, 0, reupdate_callback}, OPT_BIT(0, "ignore-missing", &refresh_args.flags, N_("ignore files missing from worktree"), REFRESH_IGNORE_MISSING), diff --git a/parse-options-cb.c b/parse-options-cb.c index e2f3eae..e05bcea 100644 --- a/parse-options-cb.c +++ b/parse-options-cb.c @@ -170,7 +170,8 @@ int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset) * "-h" output even if it's not being handled directly by * parse_options(). */ -int parse_opt_unknown_cb(const struct option *opt, const char *arg, int unset) +int parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, + const struct option *opt, int unset) { return -2; } diff --git a/parse-options.c b/parse-options.c index 62d94ca..37a56d0 100644 --- a/parse-options.c +++ b/parse-options.c @@ -93,7 +93,7 @@ static int get_value(struct parse_opt_ctx_t *p, switch (opt->type) { case OPTION_LOWLEVEL_CALLBACK: - return (*(parse_opt_ll_cb *)opt->callback)(p, opt, unset); + return opt->ll_callback(p, opt, unset); case OPTION_BIT: if (unset) @@ -408,6 +408,19 @@ static void parse_options_check(const struct option *opts) if ((opts->flags & PARSE_OPT_OPTARG) || !(opts->flags & PARSE_OPT_NOARG)) err |= optbug(opts, "should not accept an argument"); + break; + case OPTION_CALLBACK: + if (!opts->callback) + BUG("OPTION_CALLBACK needs a callback"); + if (opts->ll_callback) + BUG("OPTION_CALLBACK needs no ll_callback"); + break; + case OPTION_LOWLEVEL_CALLBACK: + if (!opts->ll_callback) + BUG("OPTION_LOWLEVEL_CALLBACK needs a callback"); + if (opts->callback) + BUG("OPTION_LOWLEVEL_CALLBACK needs no high level callback"); + break; default: ; /* ok. (usually accepts an argument) */ } diff --git a/parse-options.h b/parse-options.h index c97324f..f1f2463 100644 --- a/parse-options.h +++ b/parse-options.h @@ -100,13 +100,16 @@ typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, * the option takes optional argument. * * `callback`:: - * pointer to the callback to use for OPTION_CALLBACK or - * OPTION_LOWLEVEL_CALLBACK. + * pointer to the callback to use for OPTION_CALLBACK * * `defval`:: * default value to fill (*->value) with for PARSE_OPT_OPTARG. * OPTION_{BIT,SET_INT} store the {mask,integer} to put in the value when met. * CALLBACKS can use it like they want. + * + * `ll_callback`:: + * pointer to the callback to use for OPTION_LOWLEVEL_CALLBACK + * */ struct option { enum parse_opt_type type; @@ -119,6 +122,7 @@ struct option { int flags; parse_opt_cb *callback; intptr_t defval; + parse_opt_ll_cb *ll_callback; intptr_t extra; }; @@ -137,7 +141,7 @@ struct option { #define OPT_BIT(s, l, v, h, b) OPT_BIT_F(s, l, v, h, b, 0) #define OPT_BITOP(s, l, v, h, set, clear) { OPTION_BITOP, (s), (l), (v), NULL, (h), \ PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, \ - (set), (clear) } + (set), NULL, (clear) } #define OPT_NEGBIT(s, l, v, h, b) { OPTION_NEGBIT, (s), (l), (v), NULL, \ (h), PARSE_OPT_NOARG, NULL, (b) } #define OPT_COUNTUP(s, l, v, h) OPT_COUNTUP_F(s, l, v, h, 0) @@ -263,7 +267,7 @@ int parse_opt_commits(const struct option *, const char *, int); int parse_opt_tertiary(const struct option *, const char *, int); int parse_opt_string_list(const struct option *, const char *, int); int parse_opt_noop_cb(const struct option *, const char *, int); -int parse_opt_unknown_cb(const struct option *, const char *, int); +int parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, const struct option *, int); int parse_opt_passthru(const struct option *, const char *, int); int parse_opt_passthru_argv(const struct option *, const char *, int); -- cgit v0.10.2-6-g49f6 From f41179f16ba2fc16e31be81518536008afe2e278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:27 +0700 Subject: parse-options: avoid magic return codes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give names to these magic negative numbers. Make parse_opt_ll_cb return an enum to make clear it can actually control parse_options() with different return values (parse_opt_cb can too, but nobody needs it). Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/builtin/merge.c b/builtin/merge.c index 07839b0..de64d78 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -112,8 +112,9 @@ static int option_parse_message(const struct option *opt, return 0; } -static int option_read_message(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result option_read_message(struct parse_opt_ctx_t *ctx, + const struct option *opt, + int unset) { struct strbuf *buf = opt->value; const char *arg; diff --git a/builtin/update-index.c b/builtin/update-index.c index 727a811..21c84e5 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -847,8 +847,8 @@ static int parse_new_style_cacheinfo(const char *arg, return 0; } -static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result cacheinfo_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { struct object_id oid; unsigned int mode; @@ -873,8 +873,8 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, return 0; } -static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result stdin_cacheinfo_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { int *nul_term_line = opt->value; @@ -887,8 +887,8 @@ static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx, return 0; } -static int stdin_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result stdin_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { int *read_from_stdin = opt->value; @@ -900,8 +900,8 @@ static int stdin_callback(struct parse_opt_ctx_t *ctx, return 0; } -static int unresolve_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result unresolve_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; @@ -919,8 +919,8 @@ static int unresolve_callback(struct parse_opt_ctx_t *ctx, return 0; } -static int reupdate_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result reupdate_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; diff --git a/parse-options-cb.c b/parse-options-cb.c index e05bcea..ec01ef7 100644 --- a/parse-options-cb.c +++ b/parse-options-cb.c @@ -170,10 +170,10 @@ int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset) * "-h" output even if it's not being handled directly by * parse_options(). */ -int parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, + const struct option *opt, int unset) { - return -2; + return PARSE_OPT_UNKNOWN; } /** diff --git a/parse-options.c b/parse-options.c index 37a56d0..50c3404 100644 --- a/parse-options.c +++ b/parse-options.c @@ -20,8 +20,9 @@ int optbug(const struct option *opt, const char *reason) return error("BUG: switch '%c' %s", opt->short_name, reason); } -static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, - int flags, const char **arg) +static enum parse_opt_result get_arg(struct parse_opt_ctx_t *p, + const struct option *opt, + int flags, const char **arg) { if (p->opt) { *arg = p->opt; @@ -44,9 +45,10 @@ static void fix_filename(const char *prefix, const char **file) *file = prefix_filename(prefix, *file); } -static int opt_command_mode_error(const struct option *opt, - const struct option *all_opts, - int flags) +static enum parse_opt_result opt_command_mode_error( + const struct option *opt, + const struct option *all_opts, + int flags) { const struct option *that; struct strbuf that_name = STRBUF_INIT; @@ -69,16 +71,16 @@ static int opt_command_mode_error(const struct option *opt, error(_("%s is incompatible with %s"), optname(opt, flags), that_name.buf); strbuf_release(&that_name); - return -1; + return PARSE_OPT_ERROR; } return error(_("%s : incompatible with something else"), optname(opt, flags)); } -static int get_value(struct parse_opt_ctx_t *p, - const struct option *opt, - const struct option *all_opts, - int flags) +static enum parse_opt_result get_value(struct parse_opt_ctx_t *p, + const struct option *opt, + const struct option *all_opts, + int flags) { const char *s, *arg; const int unset = flags & OPT_UNSET; @@ -208,7 +210,8 @@ static int get_value(struct parse_opt_ctx_t *p, } } -static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options) +static enum parse_opt_result parse_short_opt(struct parse_opt_ctx_t *p, + const struct option *options) { const struct option *all_opts = options; const struct option *numopt = NULL; @@ -239,11 +242,12 @@ static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *optio free(arg); return rc; } - return -2; + return PARSE_OPT_UNKNOWN; } -static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, - const struct option *options) +static enum parse_opt_result parse_long_opt( + struct parse_opt_ctx_t *p, const char *arg, + const struct option *options) { const struct option *all_opts = options; const char *arg_end = strchrnul(arg, '='); @@ -269,7 +273,7 @@ again: if (*rest) continue; p->out[p->cpidx++] = arg - 2; - return 0; + return PARSE_OPT_DONE; } if (!rest) { /* abbreviated? */ @@ -334,11 +338,11 @@ is_abbreviated: ambiguous_option->long_name, (abbrev_flags & OPT_UNSET) ? "no-" : "", abbrev_option->long_name); - return -3; + return PARSE_OPT_HELP; } if (abbrev_option) return get_value(p, abbrev_option, all_opts, abbrev_flags); - return -2; + return PARSE_OPT_UNKNOWN; } static int parse_nodash_opt(struct parse_opt_ctx_t *p, const char *arg, @@ -590,22 +594,28 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, if (arg[1] != '-') { ctx->opt = arg + 1; switch (parse_short_opt(ctx, options)) { - case -1: + case PARSE_OPT_ERROR: return PARSE_OPT_ERROR; - case -2: + case PARSE_OPT_UNKNOWN: if (ctx->opt) check_typos(arg + 1, options); if (internal_help && *ctx->opt == 'h') goto show_usage; goto unknown; + case PARSE_OPT_NON_OPTION: + case PARSE_OPT_HELP: + case PARSE_OPT_COMPLETE: + BUG("parse_short_opt() cannot return these"); + case PARSE_OPT_DONE: + break; } if (ctx->opt) check_typos(arg + 1, options); while (ctx->opt) { switch (parse_short_opt(ctx, options)) { - case -1: + case PARSE_OPT_ERROR: return PARSE_OPT_ERROR; - case -2: + case PARSE_OPT_UNKNOWN: if (internal_help && *ctx->opt == 'h') goto show_usage; @@ -617,6 +627,12 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, ctx->argv[0] = xstrdup(ctx->opt - 1); *(char *)ctx->argv[0] = '-'; goto unknown; + case PARSE_OPT_NON_OPTION: + case PARSE_OPT_COMPLETE: + case PARSE_OPT_HELP: + BUG("parse_short_opt() cannot return these"); + case PARSE_OPT_DONE: + break; } } continue; @@ -635,12 +651,17 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, if (internal_help && !strcmp(arg + 2, "help")) goto show_usage; switch (parse_long_opt(ctx, arg + 2, options)) { - case -1: + case PARSE_OPT_ERROR: return PARSE_OPT_ERROR; - case -2: + case PARSE_OPT_UNKNOWN: goto unknown; - case -3: + case PARSE_OPT_HELP: goto show_usage; + case PARSE_OPT_NON_OPTION: + case PARSE_OPT_COMPLETE: + BUG("parse_long_opt() cannot return these"); + case PARSE_OPT_DONE: + break; } continue; unknown: diff --git a/parse-options.h b/parse-options.h index f1f2463..4e49185 100644 --- a/parse-options.h +++ b/parse-options.h @@ -49,8 +49,8 @@ struct option; typedef int parse_opt_cb(const struct option *, const char *arg, int unset); struct parse_opt_ctx_t; -typedef int parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset); +typedef enum parse_opt_result parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, + const struct option *opt, int unset); /* * `type`:: @@ -222,12 +222,12 @@ const char *optname(const struct option *opt, int flags); /*----- incremental advanced APIs -----*/ -enum { - PARSE_OPT_COMPLETE = -2, - PARSE_OPT_HELP = -1, - PARSE_OPT_DONE, +enum parse_opt_result { + PARSE_OPT_COMPLETE = -3, + PARSE_OPT_HELP = -2, + PARSE_OPT_ERROR = -1, /* must be the same as error() */ + PARSE_OPT_DONE = 0, /* fixed so that "return 0" works */ PARSE_OPT_NON_OPTION, - PARSE_OPT_ERROR, PARSE_OPT_UNKNOWN }; -- cgit v0.10.2-6-g49f6 From 3ebbe289896a698b99c91b797440563272dcd716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:28 +0700 Subject: parse-options: allow ll_callback with OPTION_CALLBACK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OPTION_CALLBACK is much simpler/safer to use, but parse_opt_cb does not allow access to parse_opt_ctx_t, which sometimes is useful (e.g. to obtain the prefix). Extending parse_opt_cb to take parse_opt_cb could result in a lot of changes. Instead let's just allow ll_callback to be used with OPTION_CALLBACK. The user will have to be careful, not to change anything in ctx, or return wrong result code. But that's the price for ll_callback. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/builtin/merge.c b/builtin/merge.c index de64d78..563a16f 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -114,11 +114,13 @@ static int option_parse_message(const struct option *opt, static enum parse_opt_result option_read_message(struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg_not_used, int unset) { struct strbuf *buf = opt->value; const char *arg; + BUG_ON_OPT_ARG(arg_not_used); if (unset) BUG("-F cannot be negated"); diff --git a/builtin/update-index.c b/builtin/update-index.c index 21c84e5..7abde20 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -848,13 +848,15 @@ static int parse_new_style_cacheinfo(const char *arg, } static enum parse_opt_result cacheinfo_callback( - struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { struct object_id oid; unsigned int mode; const char *path; BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) { if (add_cacheinfo(mode, &oid, path, 0)) @@ -874,11 +876,13 @@ static enum parse_opt_result cacheinfo_callback( } static enum parse_opt_result stdin_cacheinfo_callback( - struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *nul_term_line = opt->value; BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); if (ctx->argc != 1) return error("option '%s' must be the last argument", opt->long_name); @@ -888,11 +892,13 @@ static enum parse_opt_result stdin_cacheinfo_callback( } static enum parse_opt_result stdin_callback( - struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *read_from_stdin = opt->value; BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); if (ctx->argc != 1) return error("option '%s' must be the last argument", opt->long_name); @@ -901,12 +907,14 @@ static enum parse_opt_result stdin_callback( } static enum parse_opt_result unresolve_callback( - struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); /* consume remaining arguments. */ *has_errors = do_unresolve(ctx->argc, ctx->argv, @@ -920,12 +928,14 @@ static enum parse_opt_result unresolve_callback( } static enum parse_opt_result reupdate_callback( - struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); /* consume remaining arguments. */ setup_work_tree(); diff --git a/parse-options-cb.c b/parse-options-cb.c index ec01ef7..2733393 100644 --- a/parse-options-cb.c +++ b/parse-options-cb.c @@ -171,8 +171,10 @@ int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset) * parse_options(). */ enum parse_opt_result parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) + const struct option *opt, + const char *arg, int unset) { + BUG_ON_OPT_ARG(arg); return PARSE_OPT_UNKNOWN; } diff --git a/parse-options.c b/parse-options.c index 50c3404..cec7452 100644 --- a/parse-options.c +++ b/parse-options.c @@ -95,7 +95,7 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p, switch (opt->type) { case OPTION_LOWLEVEL_CALLBACK: - return opt->ll_callback(p, opt, unset); + return opt->ll_callback(p, opt, NULL, unset); case OPTION_BIT: if (unset) @@ -161,16 +161,27 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p, return err; case OPTION_CALLBACK: + { + const char *p_arg = NULL; + int p_unset; + if (unset) - return (*opt->callback)(opt, NULL, 1) ? (-1) : 0; - if (opt->flags & PARSE_OPT_NOARG) - return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) - return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; - if (get_arg(p, opt, flags, &arg)) + p_unset = 1; + else if (opt->flags & PARSE_OPT_NOARG) + p_unset = 0; + else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) + p_unset = 0; + else if (get_arg(p, opt, flags, &arg)) return -1; - return (*opt->callback)(opt, arg, 0) ? (-1) : 0; - + else { + p_unset = 0; + p_arg = arg; + } + if (opt->callback) + return (*opt->callback)(opt, p_arg, p_unset) ? (-1) : 0; + else + return (*opt->ll_callback)(p, opt, p_arg, p_unset); + } case OPTION_INTEGER: if (unset) { *(int *)opt->value = 0; @@ -238,7 +249,10 @@ static enum parse_opt_result parse_short_opt(struct parse_opt_ctx_t *p, len++; arg = xmemdupz(p->opt, len); p->opt = p->opt[len] ? p->opt + len : NULL; - rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0; + if (numopt->callback) + rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0; + else + rc = (*numopt->ll_callback)(p, numopt, arg, 0); free(arg); return rc; } @@ -414,10 +428,10 @@ static void parse_options_check(const struct option *opts) err |= optbug(opts, "should not accept an argument"); break; case OPTION_CALLBACK: - if (!opts->callback) - BUG("OPTION_CALLBACK needs a callback"); - if (opts->ll_callback) - BUG("OPTION_CALLBACK needs no ll_callback"); + if (!opts->callback && !opts->ll_callback) + BUG("OPTION_CALLBACK needs one callback"); + if (opts->callback && opts->ll_callback) + BUG("OPTION_CALLBACK can't have two callbacks"); break; case OPTION_LOWLEVEL_CALLBACK: if (!opts->ll_callback) diff --git a/parse-options.h b/parse-options.h index 4e49185..ce75278 100644 --- a/parse-options.h +++ b/parse-options.h @@ -50,7 +50,8 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset); struct parse_opt_ctx_t; typedef enum parse_opt_result parse_opt_ll_cb(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset); + const struct option *opt, + const char *arg, int unset); /* * `type`:: @@ -267,7 +268,7 @@ int parse_opt_commits(const struct option *, const char *, int); int parse_opt_tertiary(const struct option *, const char *, int); int parse_opt_string_list(const struct option *, const char *, int); int parse_opt_noop_cb(const struct option *, const char *, int); -int parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, const struct option *, int); +int parse_opt_unknown_cb(struct parse_opt_ctx_t *ctx, const struct option *, const char *, int); int parse_opt_passthru(const struct option *, const char *, int); int parse_opt_passthru_argv(const struct option *, const char *, int); -- cgit v0.10.2-6-g49f6 From 4a1b13a3972efb0cf90143ebba88e309af2f41be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:29 +0700 Subject: diff.h: keep forward struct declarations sorted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/diff.h b/diff.h index b512d04..c872a41 100644 --- a/diff.h +++ b/diff.h @@ -9,16 +9,16 @@ #include "object.h" #include "oidset.h" -struct rev_info; +struct combine_diff_path; +struct commit; +struct diff_filespec; struct diff_options; struct diff_queue_struct; -struct strbuf; -struct diff_filespec; -struct userdiff_driver; struct oid_array; -struct commit; -struct combine_diff_path; struct repository; +struct rev_info; +struct strbuf; +struct userdiff_driver; typedef int (*pathchange_fn_t)(struct diff_options *options, struct combine_diff_path *path); -- cgit v0.10.2-6-g49f6 From 2b393ef357d2fe466ba7097c9cc3ec92798ec05f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:30 +0700 Subject: diff.h: avoid bit fields in struct diff_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bitfield addresses cannot be passed around in a pointer. This makes it hard to use parse-options to set/unset them. Turn this struct to normal integers. This of course increases the size of this struct multiple times, but since we only have a handful of diff_options variables around, memory consumption is not at all a concern. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/diff.h b/diff.h index c872a41..8abe164 100644 --- a/diff.h +++ b/diff.h @@ -64,39 +64,39 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data) #define DIFF_FLAGS_INIT { 0 } struct diff_flags { - unsigned recursive:1; - unsigned tree_in_recursive:1; - unsigned binary:1; - unsigned text:1; - unsigned full_index:1; - unsigned silent_on_remove:1; - unsigned find_copies_harder:1; - unsigned follow_renames:1; - unsigned rename_empty:1; - unsigned has_changes:1; - unsigned quick:1; - unsigned no_index:1; - unsigned allow_external:1; - unsigned exit_with_status:1; - unsigned reverse_diff:1; - unsigned check_failed:1; - unsigned relative_name:1; - unsigned ignore_submodules:1; - unsigned dirstat_cumulative:1; - unsigned dirstat_by_file:1; - unsigned allow_textconv:1; - unsigned textconv_set_via_cmdline:1; - unsigned diff_from_contents:1; - unsigned dirty_submodules:1; - unsigned ignore_untracked_in_submodules:1; - unsigned ignore_dirty_submodules:1; - unsigned override_submodule_config:1; - unsigned dirstat_by_line:1; - unsigned funccontext:1; - unsigned default_follow_renames:1; - unsigned stat_with_summary:1; - unsigned suppress_diff_headers:1; - unsigned dual_color_diffed_diffs:1; + unsigned recursive; + unsigned tree_in_recursive; + unsigned binary; + unsigned text; + unsigned full_index; + unsigned silent_on_remove; + unsigned find_copies_harder; + unsigned follow_renames; + unsigned rename_empty; + unsigned has_changes; + unsigned quick; + unsigned no_index; + unsigned allow_external; + unsigned exit_with_status; + unsigned reverse_diff; + unsigned check_failed; + unsigned relative_name; + unsigned ignore_submodules; + unsigned dirstat_cumulative; + unsigned dirstat_by_file; + unsigned allow_textconv; + unsigned textconv_set_via_cmdline; + unsigned diff_from_contents; + unsigned dirty_submodules; + unsigned ignore_untracked_in_submodules; + unsigned ignore_dirty_submodules; + unsigned override_submodule_config; + unsigned dirstat_by_line; + unsigned funccontext; + unsigned default_follow_renames; + unsigned stat_with_summary; + unsigned suppress_diff_headers; + unsigned dual_color_diffed_diffs; }; static inline void diff_flags_or(struct diff_flags *a, -- cgit v0.10.2-6-g49f6 From 4a2884783949d1791ee5d720d8440d5536ebdc91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:31 +0700 Subject: diff.c: prepare to use parse_options() for parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a preparation step to start using parse_options() to parse diff/revision options instead of what we have now. There are a couple of good things from using parse_options(): - better help usage - easier to add new options - better completion support - help usage generation - better integration with main command option parser. We can just concat the main command's option array and diffopt's together and parse all in one go. - detect colidding options (e.g. --reverse is used by revision code, so diff code can't use it as long name for -R) - consistent syntax, e.g. option that takes mandatory argument will now accept both "--option=value" and "--option value". The plan is migrate all diff/rev options to parse_options(). Then we could get rid of diff_opt_parse() and expose parseopts[] directly to the caller. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/diff.c b/diff.c index 1b5f276..80b4af2 100644 --- a/diff.c +++ b/diff.c @@ -23,6 +23,7 @@ #include "argv-array.h" #include "graph.h" #include "packfile.h" +#include "parse-options.h" #include "help.h" #ifdef NO_FAST_WORKING_DIRECTORY @@ -4425,6 +4426,8 @@ static void run_checkdiff(struct diff_filepair *p, struct diff_options *o) builtin_checkdiff(name, other, attr_path, p->one, p->two, o); } +static void prep_parse_options(struct diff_options *options); + void repo_diff_setup(struct repository *r, struct diff_options *options) { memcpy(options, &default_diff_options, sizeof(*options)); @@ -4466,6 +4469,8 @@ void repo_diff_setup(struct repository *r, struct diff_options *options) options->color_moved = diff_color_moved_default; options->color_moved_ws_handling = diff_color_moved_ws_default; + + prep_parse_options(options); } void diff_setup_done(struct diff_options *options) @@ -4569,6 +4574,8 @@ void diff_setup_done(struct diff_options *options) if (!options->use_color || external_diff()) options->color_moved = 0; + + FREE_AND_NULL(options->parseopts); } static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val) @@ -4860,6 +4867,16 @@ static int parse_objfind_opt(struct diff_options *opt, const char *arg) return 1; } +static void prep_parse_options(struct diff_options *options) +{ + struct option parseopts[] = { + OPT_END() + }; + + ALLOC_ARRAY(options->parseopts, ARRAY_SIZE(parseopts)); + memcpy(options->parseopts, parseopts, sizeof(parseopts)); +} + int diff_opt_parse(struct diff_options *options, const char **av, int ac, const char *prefix) { @@ -4870,6 +4887,16 @@ int diff_opt_parse(struct diff_options *options, if (!prefix) prefix = ""; + ac = parse_options(ac, av, prefix, options->parseopts, NULL, + PARSE_OPT_KEEP_DASHDASH | + PARSE_OPT_KEEP_UNKNOWN | + PARSE_OPT_NO_INTERNAL_HELP | + PARSE_OPT_ONE_SHOT | + PARSE_OPT_STOP_AT_NON_OPTION); + + if (ac) + return ac; + /* Output format options */ if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch") || opt_arg(arg, 'U', "unified", &options->context)) diff --git a/diff.h b/diff.h index 8abe164..d9ad73f 100644 --- a/diff.h +++ b/diff.h @@ -15,6 +15,7 @@ struct diff_filespec; struct diff_options; struct diff_queue_struct; struct oid_array; +struct option; struct repository; struct rev_info; struct strbuf; @@ -229,6 +230,7 @@ struct diff_options { unsigned color_moved_ws_handling; struct repository *repo; + struct option *parseopts; }; void diff_emit_submodule_del(struct diff_options *o, const char *line); -- cgit v0.10.2-6-g49f6 From cc013c224cfc73cf7d29ce4d336749f00c3bf1c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:32 +0700 Subject: diff.c: convert -u|-p|--patch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/diff.c b/diff.c index 80b4af2..a4a40e4 100644 --- a/diff.c +++ b/diff.c @@ -4870,6 +4870,13 @@ static int parse_objfind_opt(struct diff_options *opt, const char *arg) static void prep_parse_options(struct diff_options *options) { struct option parseopts[] = { + OPT_GROUP(N_("Diff output format options")), + OPT_BITOP('p', "patch", &options->output_format, + N_("generate patch"), + DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT), + OPT_BITOP('u', NULL, &options->output_format, + N_("generate patch"), + DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT), OPT_END() }; @@ -4898,8 +4905,7 @@ int diff_opt_parse(struct diff_options *options, return ac; /* Output format options */ - if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch") - || opt_arg(arg, 'U', "unified", &options->context)) + if (opt_arg(arg, 'U', "unified", &options->context)) enable_patch_output(&options->output_format); else if (!strcmp(arg, "--raw")) options->output_format |= DIFF_FORMAT_RAW; -- cgit v0.10.2-6-g49f6 From d473e2e0e8eedf2ab07ddc545e00bff7c8f450e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:33 +0700 Subject: diff.c: convert -U|--unified MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index b94d332..0711734 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -36,7 +36,7 @@ endif::git-format-patch[] -U:: --unified=:: Generate diffs with lines of context instead of - the usual three. + the usual three. Implies `--patch`. ifndef::git-format-patch[] Implies `-p`. endif::git-format-patch[] diff --git a/diff.c b/diff.c index a4a40e4..0931582 100644 --- a/diff.c +++ b/diff.c @@ -4867,6 +4867,22 @@ static int parse_objfind_opt(struct diff_options *opt, const char *arg) return 1; } +static int diff_opt_unified(const struct option *opt, + const char *arg, int unset) +{ + struct diff_options *options = opt->value; + char *s; + + BUG_ON_OPT_NEG(unset); + + options->context = strtol(arg, &s, 10); + if (*s) + return error(_("%s expects a numerical value"), "--unified"); + enable_patch_output(&options->output_format); + + return 0; +} + static void prep_parse_options(struct diff_options *options) { struct option parseopts[] = { @@ -4877,6 +4893,9 @@ static void prep_parse_options(struct diff_options *options) OPT_BITOP('u', NULL, &options->output_format, N_("generate patch"), DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT), + OPT_CALLBACK_F('U', "unified", options, N_(""), + N_("generate diffs with lines context"), + PARSE_OPT_NONEG, diff_opt_unified), OPT_END() }; @@ -4905,9 +4924,7 @@ int diff_opt_parse(struct diff_options *options, return ac; /* Output format options */ - if (opt_arg(arg, 'U', "unified", &options->context)) - enable_patch_output(&options->output_format); - else if (!strcmp(arg, "--raw")) + if (!strcmp(arg, "--raw")) options->output_format |= DIFF_FORMAT_RAW; else if (!strcmp(arg, "--patch-with-raw")) { enable_patch_output(&options->output_format); diff --git a/parse-options.h b/parse-options.h index ce75278..7d83e29 100644 --- a/parse-options.h +++ b/parse-options.h @@ -134,6 +134,8 @@ struct option { #define OPT_SET_INT_F(s, l, v, h, i, f) { OPTION_SET_INT, (s), (l), (v), NULL, \ (h), PARSE_OPT_NOARG | (f), NULL, (i) } #define OPT_BOOL_F(s, l, v, h, f) OPT_SET_INT_F(s, l, v, h, 1, f) +#define OPT_CALLBACK_F(s, l, v, a, h, f, cb) \ + { OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), (cb) } #define OPT_END() { OPTION_END } #define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, \ @@ -164,8 +166,7 @@ struct option { #define OPT_EXPIRY_DATE(s, l, v, h) \ { OPTION_CALLBACK, (s), (l), (v), N_("expiry-date"),(h), 0, \ parse_opt_expiry_date_cb } -#define OPT_CALLBACK(s, l, v, a, h, f) \ - { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } +#define OPT_CALLBACK(s, l, v, a, h, f) OPT_CALLBACK_F(s, l, v, a, h, 0, f) #define OPT_NUMBER_CALLBACK(v, h, f) \ { OPTION_NUMBER, 0, NULL, (v), NULL, (h), \ PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) } -- cgit v0.10.2-6-g49f6 From 7fd9a1ba039b683f596d10bacbf892fa5e8f202f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:34 +0700 Subject: diff.c: convert -W|--[no-]function-context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/diff.c b/diff.c index 0931582..8f70101 100644 --- a/diff.c +++ b/diff.c @@ -4896,6 +4896,8 @@ static void prep_parse_options(struct diff_options *options) OPT_CALLBACK_F('U', "unified", options, N_(""), N_("generate diffs with lines context"), PARSE_OPT_NONEG, diff_opt_unified), + OPT_BOOL('W', "function-context", &options->flags.funccontext, + N_("generate diffs with lines context")), OPT_END() }; @@ -5212,12 +5214,6 @@ int diff_opt_parse(struct diff_options *options, else if (opt_arg(arg, '\0', "inter-hunk-context", &options->interhunkcontext)) ; - else if (!strcmp(arg, "-W")) - options->flags.funccontext = 1; - else if (!strcmp(arg, "--function-context")) - options->flags.funccontext = 1; - else if (!strcmp(arg, "--no-function-context")) - options->flags.funccontext = 0; else if ((argcount = parse_long_opt("output", av, &optarg))) { char *path = prefix_filename(prefix, optarg); options->file = xfopen(path, "w"); -- cgit v0.10.2-6-g49f6 From ed88148674502893790bf13d70154c157a489a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sun, 27 Jan 2019 07:35:35 +0700 Subject: diff.c: convert --raw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano diff --git a/diff.c b/diff.c index 8f70101..4bc9df7 100644 --- a/diff.c +++ b/diff.c @@ -4898,6 +4898,9 @@ static void prep_parse_options(struct diff_options *options) PARSE_OPT_NONEG, diff_opt_unified), OPT_BOOL('W', "function-context", &options->flags.funccontext, N_("generate diffs with lines context")), + OPT_BIT_F(0, "raw", &options->output_format, + N_("generate the diff in raw format"), + DIFF_FORMAT_RAW, PARSE_OPT_NONEG), OPT_END() }; @@ -4926,9 +4929,7 @@ int diff_opt_parse(struct diff_options *options, return ac; /* Output format options */ - if (!strcmp(arg, "--raw")) - options->output_format |= DIFF_FORMAT_RAW; - else if (!strcmp(arg, "--patch-with-raw")) { + if (!strcmp(arg, "--patch-with-raw")) { enable_patch_output(&options->output_format); options->output_format |= DIFF_FORMAT_RAW; } else if (!strcmp(arg, "--numstat")) -- cgit v0.10.2-6-g49f6