add-patch: split out `struct interactive_options`

The `struct add_p_opt` is reused both by our infra for "git add -p" and "git add -i". Users of `run_add_i()` for example are expected to pass `struct add_p_opt`. This is somewhat confusing and raises the question of which options apply to what part of the stack. But things are even more confusing than that: while callers are expected to pass in `struct add_p_opt`, these options ultimately get used to initialize a `struct add_i_state` that is used by both subsystems. So we are basically going full circle here. Refactor the code and split out a new `struct interactive_options` that hosts common options used by both. These options are then applied to a `struct interactive_config` that hosts common configuration. This refactoring doesn't yet fully detangle the two subsystems from one another, as we still end up calling `init_add_i_state()` in the "git add -p" subsystem. This will be fixed in a subsequent commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 2, 2026 at 13:13 UTC e3d4d7787cc3b2f0281e808042ceaa08e05c281b
10 files changed +290 -258
add-interactive.c
+37 -140
@@ -3,7 +3,6 @@
3 #include "git-compat-util.h"
4 #include "add-interactive.h"
5 #include "color.h"
6 -#include "config.h"
6 #include "diffcore.h"
7 #include "gettext.h"
8 #include "hash.h"
@@ -20,120 +19,18 @@
19 #include "prompt.h"
20 #include "tree.h"
21
23 -static void init_color(struct repository *r, enum git_colorbool use_color,
24 - const char *section_and_slot, char *dst,
25 - const char *default_color)
26 -{
27 - char *key = xstrfmt("color.%s", section_and_slot);
28 - const char *value;
29 -
30 - if (!want_color(use_color))
31 - dst[0] = '\0';
32 - else if (repo_config_get_value(r, key, &value) ||
33 - color_parse(value, dst))
34 - strlcpy(dst, default_color, COLOR_MAXLEN);
35 -
36 - free(key);
37 -}
38 -
39 -static enum git_colorbool check_color_config(struct repository *r, const char *var)
40 -{
41 - const char *value;
42 - enum git_colorbool ret;
43 -
44 - if (repo_config_get_value(r, var, &value))
45 - ret = GIT_COLOR_UNKNOWN;
46 - else
47 - ret = git_config_colorbool(var, value);
48 -
49 - /*
50 - * Do not rely on want_color() to fall back to color.ui for us. It uses
51 - * the value parsed by git_color_config(), which may not have been
52 - * called by the main command.
53 - */
54 - if (ret == GIT_COLOR_UNKNOWN &&
55 - !repo_config_get_value(r, "color.ui", &value))
56 - ret = git_config_colorbool("color.ui", value);
57 -
58 - return ret;
59 -}
60 -
22 void init_add_i_state(struct add_i_state *s, struct repository *r,
62 - struct add_p_opt *add_p_opt)
23 + struct interactive_options *opts)
24 {
25 s->r = r;
65 - s->context = -1;
66 - s->interhunkcontext = -1;
67 - s->auto_advance = add_p_opt->auto_advance;
68 -
69 - s->use_color_interactive = check_color_config(r, "color.interactive");
70 -
71 - init_color(r, s->use_color_interactive, "interactive.header",
72 - s->header_color, GIT_COLOR_BOLD);
73 - init_color(r, s->use_color_interactive, "interactive.help",
74 - s->help_color, GIT_COLOR_BOLD_RED);
75 - init_color(r, s->use_color_interactive, "interactive.prompt",
76 - s->prompt_color, GIT_COLOR_BOLD_BLUE);
77 - init_color(r, s->use_color_interactive, "interactive.error",
78 - s->error_color, GIT_COLOR_BOLD_RED);
79 - strlcpy(s->reset_color_interactive,
80 - want_color(s->use_color_interactive) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
81 -
82 - s->use_color_diff = check_color_config(r, "color.diff");
83 -
84 - init_color(r, s->use_color_diff, "diff.frag", s->fraginfo_color,
85 - diff_get_color(s->use_color_diff, DIFF_FRAGINFO));
86 - init_color(r, s->use_color_diff, "diff.context", s->context_color,
87 - "fall back");
88 - if (!strcmp(s->context_color, "fall back"))
89 - init_color(r, s->use_color_diff, "diff.plain",
90 - s->context_color,
91 - diff_get_color(s->use_color_diff, DIFF_CONTEXT));
92 - init_color(r, s->use_color_diff, "diff.old", s->file_old_color,
93 - diff_get_color(s->use_color_diff, DIFF_FILE_OLD));
94 - init_color(r, s->use_color_diff, "diff.new", s->file_new_color,
95 - diff_get_color(s->use_color_diff, DIFF_FILE_NEW));
96 - strlcpy(s->reset_color_diff,
97 - want_color(s->use_color_diff) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
98 -
99 - FREE_AND_NULL(s->interactive_diff_filter);
100 - repo_config_get_string(r, "interactive.difffilter",
101 - &s->interactive_diff_filter);
102 -
103 - FREE_AND_NULL(s->interactive_diff_algorithm);
104 - repo_config_get_string(r, "diff.algorithm",
105 - &s->interactive_diff_algorithm);
106 -
107 - if (!repo_config_get_int(r, "diff.context", &s->context))
108 - if (s->context < 0)
109 - die(_("%s cannot be negative"), "diff.context");
110 - if (!repo_config_get_int(r, "diff.interHunkContext", &s->interhunkcontext))
111 - if (s->interhunkcontext < 0)
112 - die(_("%s cannot be negative"), "diff.interHunkContext");
113 -
114 - repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
115 - if (s->use_single_key)
116 - setbuf(stdin, NULL);
117 -
118 - if (add_p_opt->context != -1) {
119 - if (add_p_opt->context < 0)
120 - die(_("%s cannot be negative"), "--unified");
121 - s->context = add_p_opt->context;
122 - }
123 - if (add_p_opt->interhunkcontext != -1) {
124 - if (add_p_opt->interhunkcontext < 0)
125 - die(_("%s cannot be negative"), "--inter-hunk-context");
126 - s->interhunkcontext = add_p_opt->interhunkcontext;
127 - }
26 + interactive_config_init(&s->cfg, r, opts);
27 }
28
29 void clear_add_i_state(struct add_i_state *s)
30 {
132 - FREE_AND_NULL(s->interactive_diff_filter);
133 - FREE_AND_NULL(s->interactive_diff_algorithm);
31 + interactive_config_clear(&s->cfg);
32 memset(s, 0, sizeof(*s));
135 - s->use_color_interactive = GIT_COLOR_UNKNOWN;
136 - s->use_color_diff = GIT_COLOR_UNKNOWN;
33 + interactive_config_clear(&s->cfg);
34 }
35
36 /*
@@ -287,7 +184,7 @@ static void list(struct add_i_state *s, struct string_list *list, int *selected,
184 return;
185
186 if (opts->header)
290 - color_fprintf_ln(stdout, s->header_color,
187 + color_fprintf_ln(stdout, s->cfg.header_color,
188 "%s", opts->header);
189
190 for (i = 0; i < list->nr; i++) {
@@ -355,7 +252,7 @@ static ssize_t list_and_choose(struct add_i_state *s,
252
253 list(s, &items->items, items->selected, &opts->list_opts);
254
358 - color_fprintf(stdout, s->prompt_color, "%s", opts->prompt);
255 + color_fprintf(stdout, s->cfg.prompt_color, "%s", opts->prompt);
256 fputs(singleton ? "> " : ">> ", stdout);
257 fflush(stdout);
258
@@ -433,7 +330,7 @@ static ssize_t list_and_choose(struct add_i_state *s,
330
331 if (from < 0 || from >= items->items.nr ||
332 (singleton && from + 1 != to)) {
436 - color_fprintf_ln(stderr, s->error_color,
333 + color_fprintf_ln(stderr, s->cfg.error_color,
334 _("Huh (%s)?"), p);
335 break;
336 } else if (singleton) {
@@ -993,7 +890,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
890 free(files->items.items[i].string);
891 } else if (item->index.unmerged ||
892 item->worktree.unmerged) {
996 - color_fprintf_ln(stderr, s->error_color,
893 + color_fprintf_ln(stderr, s->cfg.error_color,
894 _("ignoring unmerged: %s"),
895 files->items.items[i].string);
896 free(item);
@@ -1015,10 +912,10 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
912 opts->prompt = N_("Patch update");
913 count = list_and_choose(s, files, opts);
914 if (count > 0) {
1018 - struct add_p_opt add_p_opt = {
1019 - .context = s->context,
1020 - .interhunkcontext = s->interhunkcontext,
1021 - .auto_advance = s->auto_advance
915 + struct interactive_options opts = {
916 + .context = s->cfg.context,
917 + .interhunkcontext = s->cfg.interhunkcontext,
918 + .auto_advance = s->cfg.auto_advance,
919 };
920 struct strvec args = STRVEC_INIT;
921 struct pathspec ps_selected = { 0 };
@@ -1030,7 +927,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
927 parse_pathspec(&ps_selected,
928 PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
929 PATHSPEC_LITERAL_PATH, "", args.v);
1033 - res = run_add_p(s->r, ADD_P_ADD, &add_p_opt, NULL, &ps_selected);
930 + res = run_add_p(s->r, ADD_P_ADD, &opts, NULL, &ps_selected);
931 strvec_clear(&args);
932 clear_pathspec(&ps_selected);
933 }
@@ -1066,10 +963,10 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
963 struct child_process cmd = CHILD_PROCESS_INIT;
964
965 strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached", NULL);
1069 - if (s->context != -1)
1070 - strvec_pushf(&cmd.args, "--unified=%i", s->context);
1071 - if (s->interhunkcontext != -1)
1072 - strvec_pushf(&cmd.args, "--inter-hunk-context=%i", s->interhunkcontext);
966 + if (s->cfg.context != -1)
967 + strvec_pushf(&cmd.args, "--unified=%i", s->cfg.context);
968 + if (s->cfg.interhunkcontext != -1)
969 + strvec_pushf(&cmd.args, "--inter-hunk-context=%i", s->cfg.interhunkcontext);
970 strvec_pushl(&cmd.args, oid_to_hex(!is_initial ? &oid :
971 s->r->hash_algo->empty_tree), "--", NULL);
972 for (i = 0; i < files->items.nr; i++)
@@ -1087,17 +984,17 @@ static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED,
984 struct prefix_item_list *files UNUSED,
985 struct list_and_choose_options *opts UNUSED)
986 {
1090 - color_fprintf_ln(stdout, s->help_color, "status - %s",
987 + color_fprintf_ln(stdout, s->cfg.help_color, "status - %s",
988 _("show paths with changes"));
1092 - color_fprintf_ln(stdout, s->help_color, "update - %s",
989 + color_fprintf_ln(stdout, s->cfg.help_color, "update - %s",
990 _("add working tree state to the staged set of changes"));
1094 - color_fprintf_ln(stdout, s->help_color, "revert - %s",
991 + color_fprintf_ln(stdout, s->cfg.help_color, "revert - %s",
992 _("revert staged set of changes back to the HEAD version"));
1096 - color_fprintf_ln(stdout, s->help_color, "patch - %s",
993 + color_fprintf_ln(stdout, s->cfg.help_color, "patch - %s",
994 _("pick hunks and update selectively"));
1098 - color_fprintf_ln(stdout, s->help_color, "diff - %s",
995 + color_fprintf_ln(stdout, s->cfg.help_color, "diff - %s",
996 _("view diff between HEAD and index"));
1100 - color_fprintf_ln(stdout, s->help_color, "add untracked - %s",
997 + color_fprintf_ln(stdout, s->cfg.help_color, "add untracked - %s",
998 _("add contents of untracked files to the staged set of changes"));
999
1000 return 0;
@@ -1105,21 +1002,21 @@ static int run_help(struct add_i_state *s, const struct pathspec *ps UNUSED,
1002
1003 static void choose_prompt_help(struct add_i_state *s)
1004 {
1108 - color_fprintf_ln(stdout, s->help_color, "%s",
1005 + color_fprintf_ln(stdout, s->cfg.help_color, "%s",
1006 _("Prompt help:"));
1110 - color_fprintf_ln(stdout, s->help_color, "1 - %s",
1007 + color_fprintf_ln(stdout, s->cfg.help_color, "1 - %s",
1008 _("select a single item"));
1112 - color_fprintf_ln(stdout, s->help_color, "3-5 - %s",
1009 + color_fprintf_ln(stdout, s->cfg.help_color, "3-5 - %s",
1010 _("select a range of items"));
1114 - color_fprintf_ln(stdout, s->help_color, "2-3,6-9 - %s",
1011 + color_fprintf_ln(stdout, s->cfg.help_color, "2-3,6-9 - %s",
1012 _("select multiple ranges"));
1116 - color_fprintf_ln(stdout, s->help_color, "foo - %s",
1013 + color_fprintf_ln(stdout, s->cfg.help_color, "foo - %s",
1014 _("select item based on unique prefix"));
1118 - color_fprintf_ln(stdout, s->help_color, "-... - %s",
1015 + color_fprintf_ln(stdout, s->cfg.help_color, "-... - %s",
1016 _("unselect specified items"));
1120 - color_fprintf_ln(stdout, s->help_color, "* - %s",
1017 + color_fprintf_ln(stdout, s->cfg.help_color, "* - %s",
1018 _("choose all items"));
1122 - color_fprintf_ln(stdout, s->help_color, " - %s",
1019 + color_fprintf_ln(stdout, s->cfg.help_color, " - %s",
1020 _("(empty) finish selecting"));
1021 }
1022
@@ -1154,7 +1051,7 @@ static void print_command_item(int i, int selected UNUSED,
1051
1052 static void command_prompt_help(struct add_i_state *s)
1053 {
1157 - const char *help_color = s->help_color;
1054 + const char *help_color = s->cfg.help_color;
1055 color_fprintf_ln(stdout, help_color, "%s", _("Prompt help:"));
1056 color_fprintf_ln(stdout, help_color, "1 - %s",
1057 _("select a numbered item"));
@@ -1165,7 +1062,7 @@ static void command_prompt_help(struct add_i_state *s)
1062 }
1063
1064 int run_add_i(struct repository *r, const struct pathspec *ps,
1168 - struct add_p_opt *add_p_opt)
1065 + struct interactive_options *interactive_opts)
1066 {
1067 struct add_i_state s = { NULL };
1068 struct print_command_item_data data = { "[", "]" };
@@ -1208,15 +1105,15 @@ int run_add_i(struct repository *r, const struct pathspec *ps,
1105 ->util = util;
1106 }
1107
1211 - init_add_i_state(&s, r, add_p_opt);
1108 + init_add_i_state(&s, r, interactive_opts);
1109
1110 /*
1111 * When color was asked for, use the prompt color for
1112 * highlighting, otherwise use square brackets.
1113 */
1217 - if (want_color(s.use_color_interactive)) {
1218 - data.color = s.prompt_color;
1219 - data.reset = s.reset_color_interactive;
1114 + if (want_color(s.cfg.use_color_interactive)) {
1115 + data.color = s.cfg.prompt_color;
1116 + data.reset = s.cfg.reset_color_interactive;
1117 }
1118 print_file_item_data.color = data.color;
1119 print_file_item_data.reset = data.reset;
add-interactive.h
+3 -21
@@ -2,38 +2,20 @@
2 #define ADD_INTERACTIVE_H
3
4 #include "add-patch.h"
5 -#include "color.h"
5
6 struct pathspec;
7 struct repository;
8
9 struct add_i_state {
10 struct repository *r;
12 - enum git_colorbool use_color_interactive;
13 - enum git_colorbool use_color_diff;
14 - char header_color[COLOR_MAXLEN];
15 - char help_color[COLOR_MAXLEN];
16 - char prompt_color[COLOR_MAXLEN];
17 - char error_color[COLOR_MAXLEN];
18 - char reset_color_interactive[COLOR_MAXLEN];
19 -
20 - char fraginfo_color[COLOR_MAXLEN];
21 - char context_color[COLOR_MAXLEN];
22 - char file_old_color[COLOR_MAXLEN];
23 - char file_new_color[COLOR_MAXLEN];
24 - char reset_color_diff[COLOR_MAXLEN];
25 -
26 - int use_single_key;
27 - char *interactive_diff_filter, *interactive_diff_algorithm;
28 - int context, interhunkcontext;
29 - int auto_advance;
11 + struct interactive_config cfg;
12 };
13
14 void init_add_i_state(struct add_i_state *s, struct repository *r,
33 - struct add_p_opt *add_p_opt);
15 + struct interactive_options *opts);
16 void clear_add_i_state(struct add_i_state *s);
17
18 int run_add_i(struct repository *r, const struct pathspec *ps,
37 - struct add_p_opt *add_p_opt);
19 + struct interactive_options *opts);
20
21 #endif
add-patch.c
+153 -34
@@ -5,6 +5,8 @@
5 #include "add-interactive.h"
6 #include "add-patch.h"
7 #include "advice.h"
8 +#include "config.h"
9 +#include "diff.h"
10 #include "editor.h"
11 #include "environment.h"
12 #include "gettext.h"
@@ -279,6 +281,123 @@ struct add_p_state {
281 const char *revision;
282 };
283
284 +static void init_color(struct repository *r,
285 + enum git_colorbool use_color,
286 + const char *section_and_slot, char *dst,
287 + const char *default_color)
288 +{
289 + char *key = xstrfmt("color.%s", section_and_slot);
290 + const char *value;
291 +
292 + if (!want_color(use_color))
293 + dst[0] = '\0';
294 + else if (repo_config_get_value(r, key, &value) ||
295 + color_parse(value, dst))
296 + strlcpy(dst, default_color, COLOR_MAXLEN);
297 +
298 + free(key);
299 +}
300 +
301 +static enum git_colorbool check_color_config(struct repository *r, const char *var)
302 +{
303 + const char *value;
304 + enum git_colorbool ret;
305 +
306 + if (repo_config_get_value(r, var, &value))
307 + ret = GIT_COLOR_UNKNOWN;
308 + else
309 + ret = git_config_colorbool(var, value);
310 +
311 + /*
312 + * Do not rely on want_color() to fall back to color.ui for us. It uses
313 + * the value parsed by git_color_config(), which may not have been
314 + * called by the main command.
315 + */
316 + if (ret == GIT_COLOR_UNKNOWN &&
317 + !repo_config_get_value(r, "color.ui", &value))
318 + ret = git_config_colorbool("color.ui", value);
319 +
320 + return ret;
321 +}
322 +
323 +void interactive_config_init(struct interactive_config *cfg,
324 + struct repository *r,
325 + struct interactive_options *opts)
326 +{
327 + cfg->context = -1;
328 + cfg->interhunkcontext = -1;
329 + cfg->auto_advance = opts->auto_advance;
330 +
331 + cfg->use_color_interactive = check_color_config(r, "color.interactive");
332 +
333 + init_color(r, cfg->use_color_interactive, "interactive.header",
334 + cfg->header_color, GIT_COLOR_BOLD);
335 + init_color(r, cfg->use_color_interactive, "interactive.help",
336 + cfg->help_color, GIT_COLOR_BOLD_RED);
337 + init_color(r, cfg->use_color_interactive, "interactive.prompt",
338 + cfg->prompt_color, GIT_COLOR_BOLD_BLUE);
339 + init_color(r, cfg->use_color_interactive, "interactive.error",
340 + cfg->error_color, GIT_COLOR_BOLD_RED);
341 + strlcpy(cfg->reset_color_interactive,
342 + want_color(cfg->use_color_interactive) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
343 +
344 + cfg->use_color_diff = check_color_config(r, "color.diff");
345 +
346 + init_color(r, cfg->use_color_diff, "diff.frag", cfg->fraginfo_color,
347 + diff_get_color(cfg->use_color_diff, DIFF_FRAGINFO));
348 + init_color(r, cfg->use_color_diff, "diff.context", cfg->context_color,
349 + "fall back");
350 + if (!strcmp(cfg->context_color, "fall back"))
351 + init_color(r, cfg->use_color_diff, "diff.plain",
352 + cfg->context_color,
353 + diff_get_color(cfg->use_color_diff, DIFF_CONTEXT));
354 + init_color(r, cfg->use_color_diff, "diff.old", cfg->file_old_color,
355 + diff_get_color(cfg->use_color_diff, DIFF_FILE_OLD));
356 + init_color(r, cfg->use_color_diff, "diff.new", cfg->file_new_color,
357 + diff_get_color(cfg->use_color_diff, DIFF_FILE_NEW));
358 + strlcpy(cfg->reset_color_diff,
359 + want_color(cfg->use_color_diff) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);
360 +
361 + FREE_AND_NULL(cfg->interactive_diff_filter);
362 + repo_config_get_string(r, "interactive.difffilter",
363 + &cfg->interactive_diff_filter);
364 +
365 + FREE_AND_NULL(cfg->interactive_diff_algorithm);
366 + repo_config_get_string(r, "diff.algorithm",
367 + &cfg->interactive_diff_algorithm);
368 +
369 + if (!repo_config_get_int(r, "diff.context", &cfg->context))
370 + if (cfg->context < 0)
371 + die(_("%s cannot be negative"), "diff.context");
372 + if (!repo_config_get_int(r, "diff.interHunkContext", &cfg->interhunkcontext))
373 + if (cfg->interhunkcontext < 0)
374 + die(_("%s cannot be negative"), "diff.interHunkContext");
375 +
376 + repo_config_get_bool(r, "interactive.singlekey", &cfg->use_single_key);
377 + if (cfg->use_single_key)
378 + setbuf(stdin, NULL);
379 +
380 + if (opts->context != -1) {
381 + if (opts->context < 0)
382 + die(_("%s cannot be negative"), "--unified");
383 + cfg->context = opts->context;
384 + }
385 + if (opts->interhunkcontext != -1) {
386 + if (opts->interhunkcontext < 0)
387 + die(_("%s cannot be negative"), "--inter-hunk-context");
388 + cfg->interhunkcontext = opts->interhunkcontext;
389 + }
390 +}
391 +
392 +void interactive_config_clear(struct interactive_config *cfg)
393 +{
394 + FREE_AND_NULL(cfg->interactive_diff_filter);
395 + FREE_AND_NULL(cfg->interactive_diff_algorithm);
396 + memset(cfg, 0, sizeof(*cfg));
397 + cfg->use_color_interactive = GIT_COLOR_UNKNOWN;
398 + cfg->use_color_diff = GIT_COLOR_UNKNOWN;
399 +}
400 +
401 static void add_p_state_clear(struct add_p_state *s)
402 {
403 size_t i;
@@ -299,9 +418,9 @@ static void err(struct add_p_state *s, const char *fmt, ...)
418 va_list args;
419
420 va_start(args, fmt);
302 - fputs(s->s.error_color, stdout);
421 + fputs(s->s.cfg.error_color, stdout);
422 vprintf(fmt, args);
304 - puts(s->s.reset_color_interactive);
423 + puts(s->s.cfg.reset_color_interactive);
424 va_end(args);
425 }
426
@@ -424,12 +543,12 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
543 int res;
544
545 strvec_pushv(&args, s->mode->diff_cmd);
427 - if (s->s.context != -1)
428 - strvec_pushf(&args, "--unified=%i", s->s.context);
429 - if (s->s.interhunkcontext != -1)
430 - strvec_pushf(&args, "--inter-hunk-context=%i", s->s.interhunkcontext);
431 - if (s->s.interactive_diff_algorithm)
432 - strvec_pushf(&args, "--diff-algorithm=%s", s->s.interactive_diff_algorithm);
546 + if (s->s.cfg.context != -1)
547 + strvec_pushf(&args, "--unified=%i", s->s.cfg.context);
548 + if (s->s.cfg.interhunkcontext != -1)
549 + strvec_pushf(&args, "--inter-hunk-context=%i", s->s.cfg.interhunkcontext);
550 + if (s->s.cfg.interactive_diff_algorithm)
551 + strvec_pushf(&args, "--diff-algorithm=%s", s->s.cfg.interactive_diff_algorithm);
552 if (s->revision) {
553 struct object_id oid;
554 strvec_push(&args,
@@ -458,9 +577,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
577 }
578 strbuf_complete_line(plain);
579
461 - if (want_color_fd(1, s->s.use_color_diff)) {
580 + if (want_color_fd(1, s->s.cfg.use_color_diff)) {
581 struct child_process colored_cp = CHILD_PROCESS_INIT;
463 - const char *diff_filter = s->s.interactive_diff_filter;
582 + const char *diff_filter = s->s.cfg.interactive_diff_filter;
583
584 setup_child_process(s, &colored_cp, NULL);
585 xsnprintf((char *)args.v[color_arg_index], 8, "--color");
@@ -693,7 +812,7 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
812 hunk->colored_end - hunk->colored_start);
813 return;
814 } else {
696 - strbuf_addstr(out, s->s.fraginfo_color);
815 + strbuf_addstr(out, s->s.cfg.fraginfo_color);
816 p = s->colored.buf + header->colored_extra_start;
817 len = header->colored_extra_end
818 - header->colored_extra_start;
@@ -715,7 +834,7 @@ static void render_hunk(struct add_p_state *s, struct hunk *hunk,
834 if (len)
835 strbuf_add(out, p, len);
836 else if (colored)
718 - strbuf_addf(out, "%s\n", s->s.reset_color_diff);
837 + strbuf_addf(out, "%s\n", s->s.cfg.reset_color_diff);
838 else
839 strbuf_addch(out, '\n');
840 }
@@ -1104,12 +1223,12 @@ static void recolor_hunk(struct add_p_state *s, struct hunk *hunk)
1223
1224 strbuf_addstr(&s->colored,
1225 plain[current] == '-' ?
1107 - s->s.file_old_color :
1226 + s->s.cfg.file_old_color :
1227 plain[current] == '+' ?
1109 - s->s.file_new_color :
1110 - s->s.context_color);
1228 + s->s.cfg.file_new_color :
1229 + s->s.cfg.context_color);
1230 strbuf_add(&s->colored, plain + current, eol - current);
1112 - strbuf_addstr(&s->colored, s->s.reset_color_diff);
1231 + strbuf_addstr(&s->colored, s->s.cfg.reset_color_diff);
1232 if (next > eol)
1233 strbuf_add(&s->colored, plain + eol, next - eol);
1234 current = next;
@@ -1238,7 +1357,7 @@ static int run_apply_check(struct add_p_state *s,
1357
1358 static int read_single_character(struct add_p_state *s)
1359 {
1241 - if (s->s.use_single_key) {
1360 + if (s->s.cfg.use_single_key) {
1361 int res = read_key_without_echo(&s->answer);
1362 printf("%s\n", res == EOF ? "" : s->answer.buf);
1363 return res;
@@ -1252,7 +1371,7 @@ static int read_single_character(struct add_p_state *s)
1371 static int prompt_yesno(struct add_p_state *s, const char *prompt)
1372 {
1373 for (;;) {
1255 - color_fprintf(stdout, s->s.prompt_color, "%s", _(prompt));
1374 + color_fprintf(stdout, s->s.cfg.prompt_color, "%s", _(prompt));
1375 fflush(stdout);
1376 if (read_single_character(s) == EOF)
1377 return -1;
@@ -1541,7 +1660,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
1660 /* Everything decided? */
1661 if (undecided_previous < 0 && undecided_next < 0 &&
1662 hunk->use != UNDECIDED_HUNK) {
1544 - if (!s->s.auto_advance)
1663 + if (!s->s.cfg.auto_advance)
1664 all_decided = 1;
1665 else {
1666 patch_update_resp++;
@@ -1595,11 +1714,11 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
1714 permitted |= ALLOW_EDIT;
1715 strbuf_addstr(&s->buf, ",e");
1716 }
1598 - if (!s->s.auto_advance && s->file_diff_nr > 1) {
1717 + if (!s->s.cfg.auto_advance && s->file_diff_nr > 1) {
1718 permitted |= ALLOW_GOTO_NEXT_FILE;
1719 strbuf_addstr(&s->buf, ",>");
1720 }
1602 - if (!s->s.auto_advance && s->file_diff_nr > 1) {
1721 + if (!s->s.cfg.auto_advance && s->file_diff_nr > 1) {
1722 permitted |= ALLOW_GOTO_PREVIOUS_FILE;
1723 strbuf_addstr(&s->buf, ",<");
1724 }
@@ -1614,7 +1733,7 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
1733 else
1734 prompt_mode_type = PROMPT_HUNK;
1735
1617 - printf("%s(%"PRIuMAX"/%"PRIuMAX") ", s->s.prompt_color,
1736 + printf("%s(%"PRIuMAX"/%"PRIuMAX") ", s->s.cfg.prompt_color,
1737 (uintmax_t)hunk_index + 1,
1738 (uintmax_t)(file_diff->hunk_nr
1739 ? file_diff->hunk_nr
@@ -1627,8 +1746,8 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
1746 }
1747 printf(_(s->mode->prompt_mode[prompt_mode_type]),
1748 hunk_use_decision, s->buf.buf);
1630 - if (*s->s.reset_color_interactive)
1631 - fputs(s->s.reset_color_interactive, stdout);
1749 + if (*s->s.cfg.reset_color_interactive)
1750 + fputs(s->s.cfg.reset_color_interactive, stdout);
1751 fflush(stdout);
1752 if (read_single_character(s) == EOF) {
1753 patch_update_resp = s->file_diff_nr;
@@ -1679,7 +1798,7 @@ soft_increment:
1798 } else if (ch == 'q') {
1799 patch_update_resp = s->file_diff_nr;
1800 break;
1682 - } else if (!s->s.auto_advance && s->answer.buf[0] == '>') {
1801 + } else if (!s->s.cfg.auto_advance && s->answer.buf[0] == '>') {
1802 if (permitted & ALLOW_GOTO_NEXT_FILE) {
1803 if (patch_update_resp == s->file_diff_nr - 1)
1804 patch_update_resp = 0;
@@ -1690,7 +1809,7 @@ soft_increment:
1809 err(s, _("No next file"));
1810 continue;
1811 }
1693 - } else if (!s->s.auto_advance && s->answer.buf[0] == '<') {
1812 + } else if (!s->s.cfg.auto_advance && s->answer.buf[0] == '<') {
1813 if (permitted & ALLOW_GOTO_PREVIOUS_FILE) {
1814 if (patch_update_resp == 0)
1815 patch_update_resp = s->file_diff_nr - 1;
@@ -1813,7 +1932,7 @@ soft_increment:
1932 err(s, _("Sorry, cannot split this hunk"));
1933 } else if (!split_hunk(s, file_diff,
1934 hunk - file_diff->hunk)) {
1816 - color_fprintf_ln(stdout, s->s.header_color,
1935 + color_fprintf_ln(stdout, s->s.cfg.header_color,
1936 _("Split into %d hunks."),
1937 (int)splittable_into);
1938 rendered_hunk_index = -1;
@@ -1831,7 +1950,7 @@ soft_increment:
1950 } else if (s->answer.buf[0] == '?') {
1951 const char *p = _(help_patch_remainder), *eol = p;
1952
1834 - color_fprintf(stdout, s->s.help_color, "%s",
1953 + color_fprintf(stdout, s->s.cfg.help_color, "%s",
1954 _(s->mode->help_patch_text));
1955
1956 /*
@@ -1855,13 +1974,13 @@ soft_increment:
1974 if (file_diff->hunk[i].use == SKIP_HUNK)
1975 skipped += 1;
1976 }
1858 - color_fprintf_ln(stdout, s->s.help_color, _(p),
1977 + color_fprintf_ln(stdout, s->s.cfg.help_color, _(p),
1978 total, used, skipped);
1979 }
1980 if (*p != '?' && !strchr(s->buf.buf, *p))
1981 continue;
1982
1864 - color_fprintf_ln(stdout, s->s.help_color,
1983 + color_fprintf_ln(stdout, s->s.cfg.help_color,
1984 "%.*s", (int)(eol - p), p);
1985 }
1986 } else {
@@ -1870,7 +1989,7 @@ soft_increment:
1989 }
1990 }
1991
1873 - if (s->s.auto_advance)
1992 + if (s->s.cfg.auto_advance)
1993 apply_patch(s, file_diff);
1994
1995 putchar('\n');
@@ -1878,7 +1997,7 @@ soft_increment:
1997 }
1998
1999 int run_add_p(struct repository *r, enum add_p_mode mode,
1881 - struct add_p_opt *o, const char *revision,
2000 + struct interactive_options *opts, const char *revision,
2001 const struct pathspec *ps)
2002 {
2003 struct add_p_state s = {
@@ -1886,7 +2005,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
2005 };
2006 size_t i, binary_count = 0;
2007
1889 - init_add_i_state(&s.s, r, o);
2008 + init_add_i_state(&s.s, r, opts);
2009
2010 if (mode == ADD_P_STASH)
2011 s.mode = &patch_mode_stash;
@@ -1932,7 +2051,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
2051 if ((i = patch_update_file(&s, i)) == s.file_diff_nr)
2052 break;
2053 }
1935 - if (!s.s.auto_advance)
2054 + if (!s.s.cfg.auto_advance)
2055 for (i = 0; i < s.file_diff_nr; i++)
2056 apply_patch(&s, s.file_diff + i);
2057
add-patch.h
+35 -3
@@ -1,16 +1,48 @@
1 #ifndef ADD_PATCH_H
2 #define ADD_PATCH_H
3
4 +#include "color.h"
5 +
6 struct pathspec;
7 struct repository;
8
7 -struct add_p_opt {
9 +struct interactive_options {
10 int context;
11 int interhunkcontext;
12 int auto_advance;
13 };
14
13 -#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1, .auto_advance = 1 }
15 +#define INTERACTIVE_OPTIONS_INIT { \
16 + .context = -1, \
17 + .interhunkcontext = -1, \
18 + .auto_advance = 1, \
19 +}
20 +
21 +struct interactive_config {
22 + enum git_colorbool use_color_interactive;
23 + enum git_colorbool use_color_diff;
24 + char header_color[COLOR_MAXLEN];
25 + char help_color[COLOR_MAXLEN];
26 + char prompt_color[COLOR_MAXLEN];
27 + char error_color[COLOR_MAXLEN];
28 + char reset_color_interactive[COLOR_MAXLEN];
29 +
30 + char fraginfo_color[COLOR_MAXLEN];
31 + char context_color[COLOR_MAXLEN];
32 + char file_old_color[COLOR_MAXLEN];
33 + char file_new_color[COLOR_MAXLEN];
34 + char reset_color_diff[COLOR_MAXLEN];
35 +
36 + int use_single_key;
37 + char *interactive_diff_filter, *interactive_diff_algorithm;
38 + int context, interhunkcontext;
39 + int auto_advance;
40 +};
41 +
42 +void interactive_config_init(struct interactive_config *cfg,
43 + struct repository *r,
44 + struct interactive_options *opts);
45 +void interactive_config_clear(struct interactive_config *cfg);
46
47 enum add_p_mode {
48 ADD_P_ADD,
@@ -21,7 +53,7 @@ enum add_p_mode {
53 };
54
55 int run_add_p(struct repository *r, enum add_p_mode mode,
24 - struct add_p_opt *o, const char *revision,
56 + struct interactive_options *opts, const char *revision,
57 const struct pathspec *ps);
58
59 #endif
builtin/add.c
+13 -13
@@ -31,7 +31,7 @@ static const char * const builtin_add_usage[] = {
31 NULL
32 };
33 static int patch_interactive, add_interactive, edit_interactive;
34 -static struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
34 +static struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
35 static int take_worktree_changes;
36 static int add_renormalize;
37 static int pathspec_file_nul;
@@ -160,7 +160,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *
160 int interactive_add(struct repository *repo,
161 const char **argv,
162 const char *prefix,
163 - int patch, struct add_p_opt *add_p_opt)
163 + int patch, struct interactive_options *interactive_opts)
164 {
165 struct pathspec pathspec;
166 int ret;
@@ -172,9 +172,9 @@ int interactive_add(struct repository *repo,
172 prefix, argv);
173
174 if (patch)
175 - ret = !!run_add_p(repo, ADD_P_ADD, add_p_opt, NULL, &pathspec);
175 + ret = !!run_add_p(repo, ADD_P_ADD, interactive_opts, NULL, &pathspec);
176 else
177 - ret = !!run_add_i(repo, &pathspec, add_p_opt);
177 + ret = !!run_add_i(repo, &pathspec, interactive_opts);
178
179 clear_pathspec(&pathspec);
180 return ret;
@@ -256,10 +256,10 @@ static struct option builtin_add_options[] = {
256 OPT_GROUP(""),
257 OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
258 OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
259 - OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
259 + OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
260 N_("auto advance to the next file when selecting hunks interactively")),
261 - OPT_DIFF_UNIFIED(&add_p_opt.context),
262 - OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
261 + OPT_DIFF_UNIFIED(&interactive_opts.context),
262 + OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
263 OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
264 OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
265 OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -402,9 +402,9 @@ int cmd_add(int argc,
402 prepare_repo_settings(repo);
403 repo->settings.command_requires_full_index = 0;
404
405 - if (add_p_opt.context < -1)
405 + if (interactive_opts.context < -1)
406 die(_("'%s' cannot be negative"), "--unified");
407 - if (add_p_opt.interhunkcontext < -1)
407 + if (interactive_opts.interhunkcontext < -1)
408 die(_("'%s' cannot be negative"), "--inter-hunk-context");
409
410 if (patch_interactive)
@@ -414,13 +414,13 @@ int cmd_add(int argc,
414 die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
415 if (pathspec_from_file)
416 die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
417 - exit(interactive_add(repo, argv + 1, prefix, patch_interactive, &add_p_opt));
417 + exit(interactive_add(repo, argv + 1, prefix, patch_interactive, &interactive_opts));
418 } else {
419 - if (add_p_opt.context != -1)
419 + if (interactive_opts.context != -1)
420 die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
421 - if (add_p_opt.interhunkcontext != -1)
421 + if (interactive_opts.interhunkcontext != -1)
422 die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
423 - if (!add_p_opt.auto_advance)
423 + if (!interactive_opts.auto_advance)
424 die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--interactive/--patch");
425 }
426
builtin/checkout.c
+2 -2
@@ -532,7 +532,7 @@ static int checkout_paths(const struct checkout_opts *opts,
532
533 if (opts->patch_mode) {
534 enum add_p_mode patch_mode;
535 - struct add_p_opt add_p_opt = {
535 + struct interactive_options interactive_opts = {
536 .context = opts->patch_context,
537 .interhunkcontext = opts->patch_interhunk_context,
538 .auto_advance = opts->auto_advance
@@ -562,7 +562,7 @@ static int checkout_paths(const struct checkout_opts *opts,
562 else
563 BUG("either flag must have been set, worktree=%d, index=%d",
564 opts->checkout_worktree, opts->checkout_index);
565 - return !!run_add_p(the_repository, patch_mode, &add_p_opt,
565 + return !!run_add_p(the_repository, patch_mode, &interactive_opts,
566 rev, &opts->pathspec);
567 }
568
builtin/commit.c
+8 -8
@@ -123,7 +123,7 @@ static const char *edit_message, *use_message;
123 static char *fixup_message, *fixup_commit, *squash_message;
124 static const char *fixup_prefix;
125 static int all, also, interactive, patch_interactive, only, amend, signoff;
126 -static struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
126 +static struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
127 static int edit_flag = -1; /* unspecified */
128 static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
129 static int config_commit_verbose = -1; /* unspecified */
@@ -357,9 +357,9 @@ static const char *prepare_index(const char **argv, const char *prefix,
357 const char *ret;
358 char *path = NULL;
359
360 - if (add_p_opt.context < -1)
360 + if (interactive_opts.context < -1)
361 die(_("'%s' cannot be negative"), "--unified");
362 - if (add_p_opt.interhunkcontext < -1)
362 + if (interactive_opts.interhunkcontext < -1)
363 die(_("'%s' cannot be negative"), "--inter-hunk-context");
364
365 if (is_status)
@@ -408,7 +408,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
408 old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
409 setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
410
411 - if (interactive_add(the_repository, argv, prefix, patch_interactive, &add_p_opt) != 0)
411 + if (interactive_add(the_repository, argv, prefix, patch_interactive, &interactive_opts) != 0)
412 die(_("interactive add failed"));
413
414 the_repository->index_file = old_repo_index_file;
@@ -433,9 +433,9 @@ static const char *prepare_index(const char **argv, const char *prefix,
433 ret = get_lock_file_path(&index_lock);
434 goto out;
435 } else {
436 - if (add_p_opt.context != -1)
436 + if (interactive_opts.context != -1)
437 die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
438 - if (add_p_opt.interhunkcontext != -1)
438 + if (interactive_opts.interhunkcontext != -1)
439 die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
440 }
441
@@ -1743,8 +1743,8 @@ int cmd_commit(int argc,
1743 OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
1744 OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
1745 OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
1746 - OPT_DIFF_UNIFIED(&add_p_opt.context),
1747 - OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
1746 + OPT_DIFF_UNIFIED(&interactive_opts.context),
1747 + OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
1748 OPT_BOOL('o', "only", &only, N_("commit only specified files")),
1749 OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit and commit-msg hooks")),
1750 OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),
builtin/reset.c
+10 -10
@@ -346,7 +346,7 @@ int cmd_reset(int argc,
346 struct object_id oid;
347 struct pathspec pathspec;
348 int intent_to_add = 0;
349 - struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
349 + struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
350 const struct option options[] = {
351 OPT__QUIET(&quiet, N_("be quiet, only report errors")),
352 OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -371,10 +371,10 @@ int cmd_reset(int argc,
371 PARSE_OPT_OPTARG,
372 option_parse_recurse_submodules_worktree_updater),
373 OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
374 - OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
374 + OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
375 N_("auto advance to the next file when selecting hunks interactively")),
376 - OPT_DIFF_UNIFIED(&add_p_opt.context),
377 - OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
376 + OPT_DIFF_UNIFIED(&interactive_opts.context),
377 + OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
378 OPT_BOOL('N', "intent-to-add", &intent_to_add,
379 N_("record only the fact that removed paths will be added later")),
380 OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -425,9 +425,9 @@ int cmd_reset(int argc,
425 oidcpy(&oid, &tree->object.oid);
426 }
427
428 - if (add_p_opt.context < -1)
428 + if (interactive_opts.context < -1)
429 die(_("'%s' cannot be negative"), "--unified");
430 - if (add_p_opt.interhunkcontext < -1)
430 + if (interactive_opts.interhunkcontext < -1)
431 die(_("'%s' cannot be negative"), "--inter-hunk-context");
432
433 prepare_repo_settings(the_repository);
@@ -438,14 +438,14 @@ int cmd_reset(int argc,
438 die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
439 trace2_cmd_mode("patch-interactive");
440 update_ref_status = !!run_add_p(the_repository, ADD_P_RESET,
441 - &add_p_opt, rev, &pathspec);
441 + &interactive_opts, rev, &pathspec);
442 goto cleanup;
443 } else {
444 - if (add_p_opt.context != -1)
444 + if (interactive_opts.context != -1)
445 die(_("the option '%s' requires '%s'"), "--unified", "--patch");
446 - if (add_p_opt.interhunkcontext != -1)
446 + if (interactive_opts.interhunkcontext != -1)
447 die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
448 - if (!add_p_opt.auto_advance)
448 + if (!interactive_opts.auto_advance)
449 die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--patch");
450 }
451
builtin/stash.c
+28 -26
@@ -1306,7 +1306,7 @@ done:
1306
1307 static int stash_patch(struct stash_info *info, const struct pathspec *ps,
1308 struct strbuf *out_patch, int quiet,
1309 - struct add_p_opt *add_p_opt)
1309 + struct interactive_options *interactive_opts)
1310 {
1311 int ret = 0;
1312 struct child_process cp_read_tree = CHILD_PROCESS_INIT;
@@ -1331,7 +1331,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
1331 old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
1332 setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
1333
1334 - ret = !!run_add_p(the_repository, ADD_P_STASH, add_p_opt, NULL, ps);
1334 + ret = !!run_add_p(the_repository, ADD_P_STASH, interactive_opts, NULL, ps);
1335
1336 the_repository->index_file = old_repo_index_file;
1337 if (old_index_env && *old_index_env)
@@ -1427,7 +1427,8 @@ done:
1427 }
1428
1429 static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_buf,
1430 - int include_untracked, int patch_mode, struct add_p_opt *add_p_opt,
1430 + int include_untracked, int patch_mode,
1431 + struct interactive_options *interactive_opts,
1432 int only_staged, struct stash_info *info, struct strbuf *patch,
1433 int quiet)
1434 {
@@ -1509,7 +1510,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
1510 untracked_commit_option = 1;
1511 }
1512 if (patch_mode) {
1512 - ret = stash_patch(info, ps, patch, quiet, add_p_opt);
1513 + ret = stash_patch(info, ps, patch, quiet, interactive_opts);
1514 if (ret < 0) {
1515 if (!quiet)
1516 fprintf_ln(stderr, _("Cannot save the current "
@@ -1595,7 +1596,8 @@ static int create_stash(int argc, const char **argv, const char *prefix UNUSED,
1596 }
1597
1598 static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int quiet,
1598 - int keep_index, int patch_mode, struct add_p_opt *add_p_opt,
1599 + int keep_index, int patch_mode,
1600 + struct interactive_options *interactive_opts,
1601 int include_untracked, int only_staged)
1602 {
1603 int ret = 0;
@@ -1667,7 +1669,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
1669 if (stash_msg)
1670 strbuf_addstr(&stash_msg_buf, stash_msg);
1671 if (do_create_stash(ps, &stash_msg_buf, include_untracked, patch_mode,
1670 - add_p_opt, only_staged, &info, &patch, quiet)) {
1672 + interactive_opts, only_staged, &info, &patch, quiet)) {
1673 ret = -1;
1674 goto done;
1675 }
@@ -1841,7 +1843,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
1843 const char *stash_msg = NULL;
1844 char *pathspec_from_file = NULL;
1845 struct pathspec ps;
1844 - struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
1846 + struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
1847 struct option options[] = {
1848 OPT_BOOL('k', "keep-index", &keep_index,
1849 N_("keep index")),
@@ -1849,10 +1851,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
1851 N_("stash staged changes only")),
1852 OPT_BOOL('p', "patch", &patch_mode,
1853 N_("stash in patch mode")),
1852 - OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
1854 + OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
1855 N_("auto advance to the next file when selecting hunks interactively")),
1854 - OPT_DIFF_UNIFIED(&add_p_opt.context),
1855 - OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
1856 + OPT_DIFF_UNIFIED(&interactive_opts.context),
1857 + OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
1858 OPT__QUIET(&quiet, N_("quiet mode")),
1859 OPT_BOOL('u', "include-untracked", &include_untracked,
1860 N_("include untracked files in stash")),
@@ -1909,21 +1911,21 @@ static int push_stash(int argc, const char **argv, const char *prefix,
1911 }
1912
1913 if (!patch_mode) {
1912 - if (add_p_opt.context != -1)
1914 + if (interactive_opts.context != -1)
1915 die(_("the option '%s' requires '%s'"), "--unified", "--patch");
1914 - if (add_p_opt.interhunkcontext != -1)
1916 + if (interactive_opts.interhunkcontext != -1)
1917 die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
1916 - if (!add_p_opt.auto_advance)
1918 + if (!interactive_opts.auto_advance)
1919 die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--patch");
1920 }
1921
1920 - if (add_p_opt.context < -1)
1922 + if (interactive_opts.context < -1)
1923 die(_("'%s' cannot be negative"), "--unified");
1922 - if (add_p_opt.interhunkcontext < -1)
1924 + if (interactive_opts.interhunkcontext < -1)
1925 die(_("'%s' cannot be negative"), "--inter-hunk-context");
1926
1927 ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
1926 - &add_p_opt, include_untracked, only_staged);
1928 + &interactive_opts, include_untracked, only_staged);
1929
1930 clear_pathspec(&ps);
1931 free(pathspec_from_file);
@@ -1948,7 +1950,7 @@ static int save_stash(int argc, const char **argv, const char *prefix,
1950 const char *stash_msg = NULL;
1951 struct pathspec ps;
1952 struct strbuf stash_msg_buf = STRBUF_INIT;
1951 - struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
1953 + struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;
1954 struct option options[] = {
1955 OPT_BOOL('k', "keep-index", &keep_index,
1956 N_("keep index")),
@@ -1956,10 +1958,10 @@ static int save_stash(int argc, const char **argv, const char *prefix,
1958 N_("stash staged changes only")),
1959 OPT_BOOL('p', "patch", &patch_mode,
1960 N_("stash in patch mode")),
1959 - OPT_BOOL(0, "auto-advance", &add_p_opt.auto_advance,
1961 + OPT_BOOL(0, "auto-advance", &interactive_opts.auto_advance,
1962 N_("auto advance to the next file when selecting hunks interactively")),
1961 - OPT_DIFF_UNIFIED(&add_p_opt.context),
1962 - OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
1963 + OPT_DIFF_UNIFIED(&interactive_opts.context),
1964 + OPT_DIFF_INTERHUNK_CONTEXT(&interactive_opts.interhunkcontext),
1965 OPT__QUIET(&quiet, N_("quiet mode")),
1966 OPT_BOOL('u', "include-untracked", &include_untracked,
1967 N_("include untracked files in stash")),
@@ -1979,22 +1981,22 @@ static int save_stash(int argc, const char **argv, const char *prefix,
1981
1982 memset(&ps, 0, sizeof(ps));
1983
1982 - if (add_p_opt.context < -1)
1984 + if (interactive_opts.context < -1)
1985 die(_("'%s' cannot be negative"), "--unified");
1984 - if (add_p_opt.interhunkcontext < -1)
1986 + if (interactive_opts.interhunkcontext < -1)
1987 die(_("'%s' cannot be negative"), "--inter-hunk-context");
1988
1989 if (!patch_mode) {
1988 - if (add_p_opt.context != -1)
1990 + if (interactive_opts.context != -1)
1991 die(_("the option '%s' requires '%s'"), "--unified", "--patch");
1990 - if (add_p_opt.interhunkcontext != -1)
1992 + if (interactive_opts.interhunkcontext != -1)
1993 die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
1992 - if (!add_p_opt.auto_advance)
1994 + if (!interactive_opts.auto_advance)
1995 die(_("the option '%s' requires '%s'"), "--no-auto-advance", "--patch");
1996 }
1997
1998 ret = do_push_stash(&ps, stash_msg, quiet, keep_index,
1997 - patch_mode, &add_p_opt, include_untracked,
1999 + patch_mode, &interactive_opts, include_untracked,
2000 only_staged);
2001
2002 strbuf_release(&stash_msg_buf);
commit.h
+1 -1
@@ -287,7 +287,7 @@ int for_each_commit_graft(each_commit_graft_fn, void *);
287 int interactive_add(struct repository *repo,
288 const char **argv,
289 const char *prefix,
290 - int patch, struct add_p_opt *add_p_opt);
290 + int patch, struct interactive_options *opts);
291
292 struct commit_extra_header {
293 struct commit_extra_header *next;