Skip to content

Commit 66ed9f6

Browse files
committed
add-patch: add diff.context command line overrides
This patch follows on from `5324cc6c34`, where builtins that accept `--patch` options now respect `diff.context` and `diff.interHunkContext` file configurations. In particular, this patch helps users who don't want to set persistent context configurations or just want a way to override them on a one-time basis, by allowing the relevant builtins to accept corresponding command line options that override the file configurations. This mimics `diff` which allows for both context file configuration and command line overrides. Signed-off-by: Leon Michalak <[email protected]>
1 parent 5324cc6 commit 66ed9f6

17 files changed

+245
-31
lines changed

Documentation/git-add.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ 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+
`-U<n>`::
108+
`--unified=<n>`::
109+
Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
110+
or 3 if the config option is unset. Implies `--interactive/--patch`.
111+
112+
`--inter-hunk-context=<n>`::
113+
Show the context between diff hunks, up to the specified _<number>_
114+
of lines, thereby fusing hunks that are close to each other.
115+
Defaults to `diff.interHunkContext` or 0 if the config option
116+
is unset. Implies `--interactive/--patch`.
117+
107118
`-e`::
108119
`--edit`::
109120
Open the diff vs. the index in an editor and let the user

Documentation/git-checkout.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,17 @@ 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+
`-U<n>`::
293+
`--unified=<n>`::
294+
Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
295+
or 3 if the config option is unset. Implies `--patch`.
296+
297+
`--inter-hunk-context=<n>`::
298+
Show the context between diff hunks, up to the specified _<number>_
299+
of lines, thereby fusing hunks that are close to each other.
300+
Defaults to `diff.interHunkContext` or 0 if the config option
301+
is unset. Implies `--patch`.
302+
292303
--ignore-other-worktrees::
293304
`git checkout` refuses when the wanted branch is already checked
294305
out or otherwise in use by another worktree. This option makes

Documentation/git-commit.adoc

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

79+
`-U<n>`::
80+
`--unified=<n>`::
81+
Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
82+
or 3 if the config option is unset. Implies `--interactive/--patch`.
83+
84+
`--inter-hunk-context=<n>`::
85+
Show the context between diff hunks, up to the specified _<number>_
86+
of lines, thereby fusing hunks that are close to each other.
87+
Defaults to `diff.interHunkContext` or 0 if the config option
88+
is unset. Implies `--interactive/--patch`.
89+
7990
`-C <commit>`::
8091
`--reuse-message=<commit>`::
8192
Take an existing _<commit>_ object, and reuse the log message

Documentation/git-reset.adoc

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

128+
`-U<n>`::
129+
`--unified=<n>`::
130+
Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
131+
or 3 if the config option is unset. Implies `--patch`.
132+
133+
`--inter-hunk-context=<n>`::
134+
Show the context between diff hunks, up to the specified _<number>_
135+
of lines, thereby fusing hunks that are close to each other.
136+
Defaults to `diff.interHunkContext` or 0 if the config option
137+
is unset. Implies `--patch`.
138+
128139
`--`::
129140
Do not interpret any more arguments as options.
130141

Documentation/git-restore.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ 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+
`-U<n>`::
56+
`--unified=<n>`::
57+
Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
58+
or 3 if the config option is unset. Implies `--patch`.
59+
60+
`--inter-hunk-context=<n>`::
61+
Show the context between diff hunks, up to the specified _<number>_
62+
of lines, thereby fusing hunks that are close to each other.
63+
Defaults to `diff.interHunkContext` or 0 if the config option
64+
is unset. Implies `--patch`.
65+
5566
`-W`::
5667
`--worktree`::
5768
`-S`::

Documentation/git-stash.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,17 @@ to learn how to operate the `--patch` mode.
208208
The `--patch` option implies `--keep-index`. You can use
209209
`--no-keep-index` to override this.
210210
211+
`-U<n>`::
212+
`--unified=<n>`::
213+
Generate diffs with _<n>_ lines of context. Defaults to `diff.context`
214+
or 3 if the config option is unset. Implies `--patch`.
215+
216+
`--inter-hunk-context=<n>`::
217+
Show the context between diff hunks, up to the specified _<number>_
218+
of lines, thereby fusing hunks that are close to each other.
219+
Defaults to `diff.interHunkContext` or 0 if the config option
220+
is unset. Implies `--patch`.
221+
211222
-S::
212223
--staged::
213224
This option is only valid for `push` and `save` commands.

add-interactive.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ 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;
4243

@@ -86,6 +87,11 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)
8687
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
8788
if (s->use_single_key)
8889
setbuf(stdin, NULL);
90+
91+
if (add_p_opt->context != -1)
92+
s->context = add_p_opt->context;
93+
if (add_p_opt->interhunkcontext != -1)
94+
s->interhunkcontext = add_p_opt->interhunkcontext;
8995
}
9096

9197
void clear_add_i_state(struct add_i_state *s)
@@ -974,6 +980,10 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
974980
opts->prompt = N_("Patch update");
975981
count = list_and_choose(s, files, opts);
976982
if (count > 0) {
983+
struct add_p_opt add_p_opt = {
984+
.context = s->context,
985+
.interhunkcontext = s->interhunkcontext,
986+
};
977987
struct strvec args = STRVEC_INIT;
978988
struct pathspec ps_selected = { 0 };
979989

@@ -984,7 +994,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
984994
parse_pathspec(&ps_selected,
985995
PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
986996
PATHSPEC_LITERAL_PATH, "", args.v);
987-
res = run_add_p(s->r, ADD_P_ADD, NULL, &ps_selected);
997+
res = run_add_p(s->r, ADD_P_ADD, &add_p_opt, NULL, &ps_selected);
988998
strvec_clear(&args);
989999
clear_pathspec(&ps_selected);
9901000
}
@@ -1120,7 +1130,8 @@ static void command_prompt_help(struct add_i_state *s)
11201130
_("(empty) select nothing"));
11211131
}
11221132

1123-
int run_add_i(struct repository *r, const struct pathspec *ps)
1133+
int run_add_i(struct repository *r, const struct pathspec *ps,
1134+
struct add_p_opt *add_p_opt)
11241135
{
11251136
struct add_i_state s = { NULL };
11261137
struct print_command_item_data data = { "[", "]" };
@@ -1163,7 +1174,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
11631174
->util = util;
11641175
}
11651176

1166-
init_add_i_state(&s, r);
1177+
init_add_i_state(&s, r, add_p_opt);
11671178

11681179
/*
11691180
* 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+
#define ADD_P_OPT_INIT { .context = -1, .interhunkcontext = -1 }
7+
8+
struct add_p_opt {
9+
int context;
10+
int interhunkcontext;
11+
};
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: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,14 +1768,15 @@ static int patch_update_file(struct add_p_state *s,
17681768
}
17691769

17701770
int run_add_p(struct repository *r, enum add_p_mode mode,
1771-
const char *revision, const struct pathspec *ps)
1771+
struct add_p_opt *o, const char *revision,
1772+
const struct pathspec *ps)
17721773
{
17731774
struct add_p_state s = {
17741775
{ r }, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
17751776
};
17761777
size_t i, binary_count = 0;
17771778

1778-
init_add_i_state(&s.s, r);
1779+
init_add_i_state(&s.s, r, o);
17791780

17801781
if (mode == ADD_P_STASH)
17811782
s.mode = &patch_mode_stash;

builtin/add.c

Lines changed: 17 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,10 @@ 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,
174+
&pathspec);
173175
else
174-
ret = !!run_add_i(repo, &pathspec);
176+
ret = !!run_add_i(repo, &pathspec, add_p_opt);
175177

176178
clear_pathspec(&pathspec);
177179
return ret;
@@ -253,6 +255,12 @@ static struct option builtin_add_options[] = {
253255
OPT_GROUP(""),
254256
OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
255257
OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
258+
OPT_INTEGER_F('U', "unified", &add_p_opt.context,
259+
N_("generate diffs with <n> lines context, implies --interactive/--patch"),
260+
PARSE_OPT_NONEG),
261+
OPT_INTEGER_F(0, "inter-hunk-context", &add_p_opt.interhunkcontext,
262+
N_("show context between diff hunks up to the specified number of lines, implies --interactive/--patch"),
263+
PARSE_OPT_NONEG),
256264
OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
257265
OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
258266
OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
@@ -398,7 +406,12 @@ int cmd_add(int argc,
398406
die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
399407
if (pathspec_from_file)
400408
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
401-
exit(interactive_add(repo, argv + 1, prefix, patch_interactive));
409+
exit(interactive_add(repo, argv + 1, prefix, patch_interactive, &add_p_opt));
410+
} else {
411+
if (add_p_opt.context != -1)
412+
die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
413+
if (add_p_opt.interhunkcontext != -1)
414+
die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
402415
}
403416

404417
if (edit_interactive) {

builtin/checkout.c

Lines changed: 25 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,12 @@ 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_INTEGER_F('U', "unified", &opts->patch_context,
1758+
N_("generate diffs with <n> lines context, implies --patch"),
1759+
PARSE_OPT_NONEG),
1760+
OPT_INTEGER_F(0, "inter-hunk-context", &opts->patch_interhunk_context,
1761+
N_("show context between diff hunks up to the specified number of lines, implies --patch"),
1762+
PARSE_OPT_NONEG),
17411763
OPT_BOOL(0, "ignore-skip-worktree-bits", &opts->ignore_skipworktree,
17421764
N_("do not limit pathspecs to sparse entries only")),
17431765
OPT_PATHSPEC_FROM_FILE(&opts->pathspec_from_file),

builtin/commit.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "environment.h"
2020
#include "diff.h"
2121
#include "commit.h"
22+
#include "add-interactive.h"
2223
#include "gettext.h"
2324
#include "revision.h"
2425
#include "wt-status.h"
@@ -122,6 +123,7 @@ static const char *edit_message, *use_message;
122123
static char *fixup_message, *fixup_commit, *squash_message;
123124
static const char *fixup_prefix;
124125
static int all, also, interactive, patch_interactive, only, amend, signoff;
126+
static struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
125127
static int edit_flag = -1; /* unspecified */
126128
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
127129
static int config_commit_verbose = -1; /* unspecified */
@@ -400,7 +402,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
400402
old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
401403
setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
402404

403-
if (interactive_add(the_repository, argv, prefix, patch_interactive) != 0)
405+
if (interactive_add(the_repository, argv, prefix, patch_interactive, &add_p_opt) != 0)
404406
die(_("interactive add failed"));
405407

406408
the_repository->index_file = old_repo_index_file;
@@ -424,6 +426,11 @@ static const char *prepare_index(const char **argv, const char *prefix,
424426
commit_style = COMMIT_NORMAL;
425427
ret = get_lock_file_path(&index_lock);
426428
goto out;
429+
} else {
430+
if (add_p_opt.context != -1)
431+
die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
432+
if (add_p_opt.interhunkcontext != -1)
433+
die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
427434
}
428435

429436
/*
@@ -1722,6 +1729,12 @@ int cmd_commit(int argc,
17221729
OPT_BOOL('i', "include", &also, N_("add specified files to index for commit")),
17231730
OPT_BOOL(0, "interactive", &interactive, N_("interactively add files")),
17241731
OPT_BOOL('p', "patch", &patch_interactive, N_("interactively add changes")),
1732+
OPT_INTEGER_F('U', "unified", &add_p_opt.context,
1733+
N_("generate diffs with <n> lines context, implies --interactive/--patch"),
1734+
PARSE_OPT_NONEG),
1735+
OPT_INTEGER_F(0, "inter-hunk-context", &add_p_opt.interhunkcontext,
1736+
N_("show context between diff hunks up to the specified number of lines, implies --interactive/--patch"),
1737+
PARSE_OPT_NONEG),
17251738
OPT_BOOL('o', "only", &only, N_("commit only specified files")),
17261739
OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit and commit-msg hooks")),
17271740
OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),

0 commit comments

Comments
 (0)