Skip to content

Commit 13ae841

Browse files
committed
Merge branch 'lm/add-p-context' into seen
"git add/etc -p" now honors diff.context configuration variable, and learns to honor -U<n> option. Comments? * lm/add-p-context: add-patch: add diff.context command line overrides add-patch: respect diff.context configuration test: refactor to use "test_config" test: refactor to use "test_grep"
2 parents 496ef81 + 1fec515 commit 13ae841

21 files changed

+390
-80
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
`-U<n>`::
2+
`--unified=<n>`::
3+
Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
4+
or 3 if the config option is unset.
5+
6+
`--inter-hunk-context=<n>`::
7+
Show the context between diff hunks, up to the specified _<number>_
8+
of lines, thereby fusing hunks that are close to each other.
9+
Defaults to `diff.interHunkContext` or 0 if the config option
10+
is unset.

Documentation/git-add.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ This effectively runs `add --interactive`, but bypasses the
104104
initial command menu and directly jumps to the `patch` subcommand.
105105
See ``Interactive mode'' for details.
106106

107+
include::diff-context-options.adoc[]
108+
107109
`-e`::
108110
`--edit`::
109111
Open the diff vs. the index in an editor and let the user

Documentation/git-checkout.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
289289
Note that this option uses the no overlay mode by default (see also
290290
`--overlay`), and currently doesn't support overlay mode.
291291
292+
include::diff-context-options.adoc[]
293+
292294
--ignore-other-worktrees::
293295
`git checkout` refuses when the wanted branch is already checked
294296
out or otherwise in use by another worktree. This option makes

Documentation/git-commit.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ OPTIONS
7676
which changes to commit. See linkgit:git-add[1] for
7777
details.
7878

79+
include::diff-context-options.adoc[]
80+
7981
`-C <commit>`::
8082
`--reuse-message=<commit>`::
8183
Take an existing _<commit>_ object, and reuse the log message

Documentation/git-reset.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ OPTIONS
125125
separated with _NUL_ character and all other characters are taken
126126
literally (including newlines and quotes).
127127

128+
include::diff-context-options.adoc[]
129+
128130
`--`::
129131
Do not interpret any more arguments as options.
130132

Documentation/git-restore.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ leave out at most one of _<rev-A>__ and _<rev-B>_, in which case it defaults to
5252
Mode" section of linkgit:git-add[1] to learn how to operate
5353
the `--patch` mode.
5454

55+
include::diff-context-options.adoc[]
56+
5557
`-W`::
5658
`--worktree`::
5759
`-S`::

Documentation/git-stash.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ to learn how to operate the `--patch` mode.
222222
The `--patch` option implies `--keep-index`. You can use
223223
`--no-keep-index` to override this.
224224
225+
include::diff-context-options.adoc[]
226+
225227
-S::
226228
--staged::
227229
This option is only valid for `push` and `save` commands.

add-interactive.c

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,16 @@ static void init_color(struct repository *r, struct add_i_state *s,
3636
free(key);
3737
}
3838

39-
void init_add_i_state(struct add_i_state *s, struct repository *r)
39+
void init_add_i_state(struct add_i_state *s, struct repository *r,
40+
struct add_p_opt *add_p_opt)
4041
{
4142
const char *value;
43+
int context;
44+
int interhunkcontext;
4245

4346
s->r = r;
47+
s->context = -1;
48+
s->interhunkcontext = -1;
4449

4550
if (repo_config_get_value(r, "color.interactive", &value))
4651
s->use_color = -1;
@@ -78,9 +83,33 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)
7883
repo_config_get_string(r, "diff.algorithm",
7984
&s->interactive_diff_algorithm);
8085

86+
if (!repo_config_get_int(r, "diff.context", &context)) {
87+
if (context < 0)
88+
die(_("%s cannot be negative"), "diff.context");
89+
else
90+
s->context = context;
91+
};
92+
if (!repo_config_get_int(r, "diff.interHunkContext", &interhunkcontext)) {
93+
if (interhunkcontext < 0)
94+
die(_("%s cannot be negative"), "diff.interHunkContext");
95+
else
96+
s->interhunkcontext = interhunkcontext;
97+
};
98+
8199
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
82100
if (s->use_single_key)
83101
setbuf(stdin, NULL);
102+
103+
if (add_p_opt->context != -1) {
104+
if (add_p_opt->context < 0)
105+
die(_("%s cannot be negative"), "--unified");
106+
s->context = add_p_opt->context;
107+
}
108+
if (add_p_opt->interhunkcontext != -1) {
109+
if (add_p_opt->interhunkcontext < 0)
110+
die(_("%s cannot be negative"), "--inter-hunk-context");
111+
s->interhunkcontext = add_p_opt->interhunkcontext;
112+
}
84113
}
85114

86115
void clear_add_i_state(struct add_i_state *s)
@@ -969,6 +998,10 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
969998
opts->prompt = N_("Patch update");
970999
count = list_and_choose(s, files, opts);
9711000
if (count > 0) {
1001+
struct add_p_opt add_p_opt = {
1002+
.context = s->context,
1003+
.interhunkcontext = s->interhunkcontext,
1004+
};
9721005
struct strvec args = STRVEC_INIT;
9731006
struct pathspec ps_selected = { 0 };
9741007

@@ -979,7 +1012,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
9791012
parse_pathspec(&ps_selected,
9801013
PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
9811014
PATHSPEC_LITERAL_PATH, "", args.v);
982-
res = run_add_p(s->r, ADD_P_ADD, NULL, &ps_selected);
1015+
res = run_add_p(s->r, ADD_P_ADD, &add_p_opt, NULL, &ps_selected);
9831016
strvec_clear(&args);
9841017
clear_pathspec(&ps_selected);
9851018
}
@@ -1014,10 +1047,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
10141047
if (count > 0) {
10151048
struct child_process cmd = CHILD_PROCESS_INIT;
10161049

1017-
strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached",
1018-
oid_to_hex(!is_initial ? &oid :
1019-
s->r->hash_algo->empty_tree),
1020-
"--", NULL);
1050+
strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached", NULL);
1051+
if (s->context != -1)
1052+
strvec_pushf(&cmd.args, "--unified=%i", s->context);
1053+
if (s->interhunkcontext != -1)
1054+
strvec_pushf(&cmd.args, "--inter-hunk-context=%i", s->interhunkcontext);
1055+
strvec_pushl(&cmd.args, oid_to_hex(!is_initial ? &oid :
1056+
s->r->hash_algo->empty_tree), "--", NULL);
10211057
for (i = 0; i < files->items.nr; i++)
10221058
if (files->selected[i])
10231059
strvec_push(&cmd.args,
@@ -1110,7 +1146,8 @@ static void command_prompt_help(struct add_i_state *s)
11101146
_("(empty) select nothing"));
11111147
}
11121148

1113-
int run_add_i(struct repository *r, const struct pathspec *ps)
1149+
int run_add_i(struct repository *r, const struct pathspec *ps,
1150+
struct add_p_opt *add_p_opt)
11141151
{
11151152
struct add_i_state s = { NULL };
11161153
struct print_command_item_data data = { "[", "]" };
@@ -1153,7 +1190,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
11531190
->util = util;
11541191
}
11551192

1156-
init_add_i_state(&s, r);
1193+
init_add_i_state(&s, r, add_p_opt);
11571194

11581195
/*
11591196
* When color was asked for, use the prompt color for

add-interactive.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33

44
#include "color.h"
55

6+
struct add_p_opt {
7+
int context;
8+
int interhunkcontext;
9+
};
10+
11+
#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 }
12+
613
struct add_i_state {
714
struct repository *r;
815
int use_color;
@@ -18,14 +25,17 @@ struct add_i_state {
1825

1926
int use_single_key;
2027
char *interactive_diff_filter, *interactive_diff_algorithm;
28+
int context, interhunkcontext;
2129
};
2230

23-
void init_add_i_state(struct add_i_state *s, struct repository *r);
31+
void init_add_i_state(struct add_i_state *s, struct repository *r,
32+
struct add_p_opt *add_p_opt);
2433
void clear_add_i_state(struct add_i_state *s);
2534

2635
struct repository;
2736
struct pathspec;
28-
int run_add_i(struct repository *r, const struct pathspec *ps);
37+
int run_add_i(struct repository *r, const struct pathspec *ps,
38+
struct add_p_opt *add_p_opt);
2939

3040
enum add_p_mode {
3141
ADD_P_ADD,
@@ -36,6 +46,7 @@ enum add_p_mode {
3646
};
3747

3848
int run_add_p(struct repository *r, enum add_p_mode mode,
39-
const char *revision, const struct pathspec *ps);
49+
struct add_p_opt *o, const char *revision,
50+
const struct pathspec *ps);
4051

4152
#endif

add-patch.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
415415
{
416416
struct strvec args = STRVEC_INIT;
417417
const char *diff_algorithm = s->s.interactive_diff_algorithm;
418+
int diff_context = s->s.context;
419+
int diff_interhunkcontext = s->s.interhunkcontext;
418420
struct strbuf *plain = &s->plain, *colored = NULL;
419421
struct child_process cp = CHILD_PROCESS_INIT;
420422
char *p, *pend, *colored_p = NULL, *colored_pend = NULL, marker = '\0';
@@ -424,6 +426,10 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps)
424426
int res;
425427

426428
strvec_pushv(&args, s->mode->diff_cmd);
429+
if (diff_context != -1)
430+
strvec_pushf(&args, "--unified=%i", diff_context);
431+
if (diff_interhunkcontext != -1)
432+
strvec_pushf(&args, "--inter-hunk-context=%i", diff_interhunkcontext);
427433
if (diff_algorithm)
428434
strvec_pushf(&args, "--diff-algorithm=%s", diff_algorithm);
429435
if (s->revision) {
@@ -1760,14 +1766,15 @@ static int patch_update_file(struct add_p_state *s,
17601766
}
17611767

17621768
int run_add_p(struct repository *r, enum add_p_mode mode,
1763-
const char *revision, const struct pathspec *ps)
1769+
struct add_p_opt *o, const char *revision,
1770+
const struct pathspec *ps)
17641771
{
17651772
struct add_p_state s = {
17661773
{ r }, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
17671774
};
17681775
size_t i, binary_count = 0;
17691776

1770-
init_add_i_state(&s.s, r);
1777+
init_add_i_state(&s.s, r, o);
17711778

17721779
if (mode == ADD_P_STASH)
17731780
s.mode = &patch_mode_stash;

builtin/add.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static const char * const builtin_add_usage[] = {
2929
NULL
3030
};
3131
static int patch_interactive, add_interactive, edit_interactive;
32+
static struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
3233
static int take_worktree_changes;
3334
static int add_renormalize;
3435
static int pathspec_file_nul;
@@ -157,7 +158,7 @@ static int refresh(struct repository *repo, int verbose, const struct pathspec *
157158
int interactive_add(struct repository *repo,
158159
const char **argv,
159160
const char *prefix,
160-
int patch)
161+
int patch, struct add_p_opt *add_p_opt)
161162
{
162163
struct pathspec pathspec;
163164
int ret;
@@ -169,9 +170,9 @@ int interactive_add(struct repository *repo,
169170
prefix, argv);
170171

171172
if (patch)
172-
ret = !!run_add_p(repo, ADD_P_ADD, NULL, &pathspec);
173+
ret = !!run_add_p(repo, ADD_P_ADD, add_p_opt, NULL, &pathspec);
173174
else
174-
ret = !!run_add_i(repo, &pathspec);
175+
ret = !!run_add_i(repo, &pathspec, add_p_opt);
175176

176177
clear_pathspec(&pathspec);
177178
return ret;
@@ -253,6 +254,8 @@ static struct option builtin_add_options[] = {
253254
OPT_GROUP(""),
254255
OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
255256
OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
257+
OPT_DIFF_UNIFIED(&add_p_opt.context),
258+
OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
256259
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
257260
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
258261
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -401,7 +404,12 @@ int cmd_add(int argc,
401404
die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
402405
if (pathspec_from_file)
403406
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
404-
exit(interactive_add(repo, argv + 1, prefix, patch_interactive));
407+
exit(interactive_add(repo, argv + 1, prefix, patch_interactive, &add_p_opt));
408+
} else {
409+
if (add_p_opt.context != -1)
410+
die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
411+
if (add_p_opt.interhunkcontext != -1)
412+
die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
405413
}
406414

407415
if (edit_interactive) {

builtin/checkout.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static const char * const restore_usage[] = {
6161

6262
struct checkout_opts {
6363
int patch_mode;
64+
int patch_context;
65+
int patch_interhunk_context;
6466
int quiet;
6567
int merge;
6668
int force;
@@ -104,7 +106,12 @@ struct checkout_opts {
104106
struct tree *source_tree;
105107
};
106108

107-
#define CHECKOUT_OPTS_INIT { .conflict_style = -1, .merge = -1 }
109+
#define CHECKOUT_OPTS_INIT { \
110+
.conflict_style = -1, \
111+
.merge = -1, \
112+
.patch_context = -1, \
113+
.patch_interhunk_context = -1, \
114+
}
108115

109116
struct branch_info {
110117
char *name; /* The short name used */
@@ -539,6 +546,10 @@ static int checkout_paths(const struct checkout_opts *opts,
539546

540547
if (opts->patch_mode) {
541548
enum add_p_mode patch_mode;
549+
struct add_p_opt add_p_opt = {
550+
.context = opts->patch_context,
551+
.interhunkcontext = opts->patch_interhunk_context,
552+
};
542553
const char *rev = new_branch_info->name;
543554
char rev_oid[GIT_MAX_HEXSZ + 1];
544555

@@ -564,8 +575,13 @@ static int checkout_paths(const struct checkout_opts *opts,
564575
else
565576
BUG("either flag must have been set, worktree=%d, index=%d",
566577
opts->checkout_worktree, opts->checkout_index);
567-
return !!run_add_p(the_repository, patch_mode, rev,
568-
&opts->pathspec);
578+
return !!run_add_p(the_repository, patch_mode, &add_p_opt,
579+
rev, &opts->pathspec);
580+
} else {
581+
if (opts->patch_context != -1)
582+
die(_("the option '%s' requires '%s'"), "--unified", "--patch");
583+
if (opts->patch_interhunk_context != -1)
584+
die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
569585
}
570586

571587
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@@ -1738,6 +1754,8 @@ static struct option *add_checkout_path_options(struct checkout_opts *opts,
17381754
N_("checkout their version for unmerged files"),
17391755
3, PARSE_OPT_NONEG),
17401756
OPT_BOOL('p', "patch", &opts->patch_mode, N_("select hunks interactively")),
1757+
OPT_DIFF_UNIFIED(&opts->patch_context),
1758+
OPT_DIFF_INTERHUNK_CONTEXT(&opts->patch_interhunk_context),
17411759
OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree,
17421760
N_("do not limit pathspecs to sparse entries only")),
17431761
OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),

0 commit comments

Comments
 (0)