Skip to content

Commit cf726da

Browse files
committed
add-patch: add diff.context command line overrides
This patch compliments the previous commit, where builtins that use add-patch infrastructure 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 commands such as diff and log, which allow for both context file configuration and command line overrides. Signed-off-by: Leon Michalak <[email protected]>
1 parent 066c72a commit cf726da

20 files changed

+251
-35
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
@@ -208,6 +208,8 @@ 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+
include::diff-context-options.adoc[]
212+
211213
-S::
212214
--staged::
213215
This option is only valid for `push` and `save` commands.

add-interactive.c

Lines changed: 28 additions & 8 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
int context;
@@ -98,6 +99,17 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)
9899
repo_config_get_bool(r, "interactive.singlekey", &s->use_single_key);
99100
if (s->use_single_key)
100101
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+
}
101113
}
102114

103115
void clear_add_i_state(struct add_i_state *s)
@@ -986,6 +998,10 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
986998
opts->prompt = N_("Patch update");
987999
count = list_and_choose(s, files, opts);
9881000
if (count > 0) {
1001+
struct add_p_opt add_p_opt = {
1002+
.context = s->context,
1003+
.interhunkcontext = s->interhunkcontext,
1004+
};
9891005
struct strvec args = STRVEC_INIT;
9901006
struct pathspec ps_selected = { 0 };
9911007

@@ -996,7 +1012,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
9961012
parse_pathspec(&ps_selected,
9971013
PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
9981014
PATHSPEC_LITERAL_PATH, "", args.v);
999-
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);
10001016
strvec_clear(&args);
10011017
clear_pathspec(&ps_selected);
10021018
}
@@ -1031,10 +1047,13 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
10311047
if (count > 0) {
10321048
struct child_process cmd = CHILD_PROCESS_INIT;
10331049

1034-
strvec_pushl(&cmd.args, "git", "diff", "-p", "--cached",
1035-
oid_to_hex(!is_initial ? &oid :
1036-
s->r->hash_algo->empty_tree),
1037-
"--", 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);
10381057
for (i = 0; i < files->items.nr; i++)
10391058
if (files->selected[i])
10401059
strvec_push(&cmd.args,
@@ -1127,7 +1146,8 @@ static void command_prompt_help(struct add_i_state *s)
11271146
_("(empty) select nothing"));
11281147
}
11291148

1130-
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)
11311151
{
11321152
struct add_i_state s = { NULL };
11331153
struct print_command_item_data data = { "[", "]" };
@@ -1170,7 +1190,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
11701190
->util = util;
11711191
}
11721192

1173-
init_add_i_state(&s, r);
1193+
init_add_i_state(&s, r, add_p_opt);
11741194

11751195
/*
11761196
* When color was asked for, use the prompt color for

add-interactive.h

Lines changed: 13 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;
@@ -21,12 +28,14 @@ struct add_i_state {
2128
int context, interhunkcontext;
2229
};
2330

24-
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);
2533
void clear_add_i_state(struct add_i_state *s);
2634

2735
struct repository;
2836
struct pathspec;
29-
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);
3039

3140
enum add_p_mode {
3241
ADD_P_ADD,
@@ -37,6 +46,7 @@ enum add_p_mode {
3746
};
3847

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

4252
#endif

add-patch.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,14 +1766,15 @@ static int patch_update_file(struct add_p_state *s,
17661766
}
17671767

17681768
int run_add_p(struct repository *r, enum add_p_mode mode,
1769-
const char *revision, const struct pathspec *ps)
1769+
struct add_p_opt *o, const char *revision,
1770+
const struct pathspec *ps)
17701771
{
17711772
struct add_p_state s = {
17721773
{ r }, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
17731774
};
17741775
size_t i, binary_count = 0;
17751776

1776-
init_add_i_state(&s.s, r);
1777+
init_add_i_state(&s.s, r, o);
17771778

17781779
if (mode == ADD_P_STASH)
17791780
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")),
@@ -398,7 +401,12 @@ int cmd_add(int argc,
398401
die(_("options '%s' and '%s' cannot be used together"), "--dry-run", "--interactive/--patch");
399402
if (pathspec_from_file)
400403
die(_("options '%s' and '%s' cannot be used together"), "--pathspec-from-file", "--interactive/--patch");
401-
exit(interactive_add(repo, argv + 1, prefix, patch_interactive));
404+
exit(interactive_add(repo, argv + 1, prefix, patch_interactive, &add_p_opt));
405+
} else {
406+
if (add_p_opt.context != -1)
407+
die(_("the option '%s' requires '%s'"), "--unified", "--interactive/--patch");
408+
if (add_p_opt.interhunkcontext != -1)
409+
die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--interactive/--patch");
402410
}
403411

404412
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),

builtin/commit.c

Lines changed: 10 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,8 @@ 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_DIFF_UNIFIED(&add_p_opt.context),
1733+
OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
17251734
OPT_BOOL('o', "only", &only, N_("commit only specified files")),
17261735
OPT_BOOL('n', "no-verify", &no_verify, N_("bypass pre-commit and commit-msg hooks")),
17271736
OPT_BOOL(0, "dry-run", &dry_run, N_("show what would be committed")),

builtin/reset.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ int cmd_reset(int argc,
346346
struct object_id oid;
347347
struct pathspec pathspec;
348348
int intent_to_add = 0;
349+
struct add_p_opt add_p_opt = ADD_P_OPT_INIT;
349350
const struct option options[] = {
350351
OPT__QUIET(&quiet, N_("be quiet, only report errors")),
351352
OPT_BOOL(0, "no-refresh", &no_refresh,
@@ -370,6 +371,8 @@ int cmd_reset(int argc,
370371
PARSE_OPT_OPTARG,
371372
option_parse_recurse_submodules_worktree_updater),
372373
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
374+
OPT_DIFF_UNIFIED(&add_p_opt.context),
375+
OPT_DIFF_INTERHUNK_CONTEXT(&add_p_opt.interhunkcontext),
373376
OPT_BOOL('N', "intent-to-add", &intent_to_add,
374377
N_("record only the fact that removed paths will be added later")),
375378
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
@@ -424,9 +427,14 @@ int cmd_reset(int argc,
424427
if (reset_type != NONE)
425428
die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
426429
trace2_cmd_mode("patch-interactive");
427-
update_ref_status = !!run_add_p(the_repository, ADD_P_RESET, rev,
428-
&pathspec);
430+
update_ref_status = !!run_add_p(the_repository, ADD_P_RESET,
431+
&add_p_opt, rev, &pathspec);
429432
goto cleanup;
433+
} else {
434+
if (add_p_opt.context != -1)
435+
die(_("the option '%s' requires '%s'"), "--unified", "--patch");
436+
if (add_p_opt.interhunkcontext != -1)
437+
die(_("the option '%s' requires '%s'"), "--inter-hunk-context", "--patch");
430438
}
431439

432440
/* git reset tree [--] paths... can be used to

0 commit comments

Comments
 (0)